# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID 5ecfc7102ccae3252062f685c12e249bbd272fdb
# Parent a75c389e4a7d23f8ab3345bf8f417d9c2fe471c0
# Parent 7f21d87ec95d093d58bbc05c0b38292202ffe079
merge with http://xenbits.xensource.com/ext/xenppc-unstable.hg
---
patches/linux-2.6.16.13/net-gso.patch | 2516
---
tools/examples/vtpm-addtodb | 10
tools/ioemu/cpu.h | 76
tools/ioemu/create_keysym_header.sh | 77
tools/ioemu/hw/acpi.c | 178
tools/ioemu/hw/i8259_stub.c | 81
tools/ioemu/hw/m48t08.c | 391
tools/ioemu/hw/m48t08.h | 12
tools/ioemu/hw/magic-load.c | 324
tools/ioemu/hw/pcnet.c | 1154
-
tools/ioemu/hw/pcnet.h | 537
tools/ioemu/hw/port-e9.c | 47
tools/ioemu/hw/sched.c | 268
tools/ioemu/hw/timer.c | 97
tools/ioemu/keyboard_rdesktop.c | 165
tools/ioemu/keymaps/convert-map | 63
tools/ioemu/main.c | 250
tools/ioemu/path.c | 147
tools/ioemu/target-i386-dm/Makefile | 406
tools/ioemu/x86_32.ld | 140
tools/libxc/xc_ia64_stubs.c | 756
-
tools/vtpm/tpm_emulator-0.3-x86_64.patch | 657
-
xen/arch/powerpc/xen.lds | 226
xen/include/asm-ia64/linux/asm/asmmacro.h | 111
.hgignore | 47
Config.mk | 2
README | 1
buildconfigs/Rules.mk | 14
buildconfigs/conf.linux-native/00_xen_to_native | 84
buildconfigs/create_config.sh | 50
buildconfigs/linux-defconfig_xen0_ia64 | 29
buildconfigs/linux-defconfig_xen0_x86_32 | 1
buildconfigs/linux-defconfig_xen0_x86_64 | 1
buildconfigs/linux-defconfig_xen_ia64 | 29
buildconfigs/linux-defconfig_xen_x86_32 | 1
buildconfigs/linux-defconfig_xen_x86_64 | 1
buildconfigs/mk.linux-2.6-native | 4
buildconfigs/mk.linux-2.6-xen | 17
config/ia64.mk | 1
config/x86_32.mk | 2
config/x86_64.mk | 2
docs/src/user.tex | 180
extras/mini-os/mm.c | 2
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 21
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 41
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 5
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c | 23
linux-2.6-xen-sparse/arch/ia64/Kconfig | 9
linux-2.6-xen-sparse/arch/ia64/kernel/gate.S | 488
linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S | 117
linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c | 77
linux-2.6-xen-sparse/arch/ia64/kernel/patch.c | 268
linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 24
linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S | 56
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c | 20
linux-2.6-xen-sparse/arch/ia64/xen/util.c | 3
linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S | 20
linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2
linux-2.6-xen-sparse/drivers/xen/Kconfig | 104
linux-2.6-xen-sparse/drivers/xen/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/blktap/Makefile | 3
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 1439
++
linux-2.6-xen-sparse/drivers/xen/blktap/common.h | 120
linux-2.6-xen-sparse/drivers/xen/blktap/interface.c | 165
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 354
linux-2.6-xen-sparse/drivers/xen/console/console.c | 33
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 135
linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 1
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c | 1
linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 11
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 3
linux-2.6-xen-sparse/drivers/xen/pciback/Makefile | 3
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c | 76
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h | 11
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c | 128
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h | 35
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 224
linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h | 2
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c | 4
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h | 2
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 18
linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h | 2
linux-2.6-xen-sparse/include/linux/skbuff.h | 5
linux-2.6-xen-sparse/net/core/dev.c | 36
patches/linux-2.6.16.13/blktap-aio-16_03_06.patch | 164
patches/linux-2.6.16.13/net-csum.patch | 15
patches/linux-2.6.16.13/net-gso-0-base.patch | 1974
+++
patches/linux-2.6.16.13/net-gso-1-check-dodgy.patch | 16
patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch | 311
patches/linux-2.6.16.13/net-gso-3-fix-errorcheck.patch | 13
patches/linux-2.6.16.13/xenoprof-generic.patch | 144
tools/Makefile | 15
tools/blktap/Makefile | 28
tools/blktap/README | 122
tools/blktap/drivers/Makefile | 76
tools/blktap/drivers/aes.c | 1319
++
tools/blktap/drivers/aes.h | 26
tools/blktap/drivers/blktapctrl.c | 704
+
tools/blktap/drivers/blktapctrl.h | 55
tools/blktap/drivers/block-aio.c | 327
tools/blktap/drivers/block-qcow.c | 1369
++
tools/blktap/drivers/block-ram.c | 296
tools/blktap/drivers/block-sync.c | 242
tools/blktap/drivers/block-vmdk.c | 415
tools/blktap/drivers/bswap.h | 202
tools/blktap/drivers/img2qcow.c | 289
tools/blktap/drivers/qcow-create.c | 80
tools/blktap/drivers/qcow2raw.c | 346
tools/blktap/drivers/tapdisk.c | 674
+
tools/blktap/drivers/tapdisk.h | 211
tools/blktap/lib/Makefile | 68
tools/blktap/lib/blkif.c | 185
tools/blktap/lib/blktaplib.h | 223
tools/blktap/lib/list.h | 55
tools/blktap/lib/xenbus.c | 387
tools/blktap/lib/xs_api.c | 364
tools/blktap/lib/xs_api.h | 50
tools/domctrl/DomU.dts.in | 2
tools/domctrl/DomU.sh | 2
tools/examples/Makefile | 5
tools/examples/README | 1
tools/examples/blktap | 15
tools/examples/vtpm-common.sh | 48
tools/examples/vtpm-impl | 58
tools/examples/xen-backend.agent | 3
tools/examples/xen-backend.rules | 1
tools/examples/xend-pci-permissive.sxp | 27
tools/examples/xend-pci-quirks.sxp | 96
tools/examples/xmexample.hvm | 15
tools/firmware/vmxassist/vmxassist.ld | 3
tools/ioemu/.cvsignore | 29
tools/ioemu/CVS/Entries | 109
tools/ioemu/CVS/Repository | 1
tools/ioemu/CVS/Root | 1
tools/ioemu/CVS/Tag | 1
tools/ioemu/Changelog | 81
tools/ioemu/LICENSE | 12
tools/ioemu/Makefile | 135
tools/ioemu/Makefile.target | 531
tools/ioemu/README | 53
tools/ioemu/README.distrib | 16
tools/ioemu/TODO | 21
tools/ioemu/VERSION | 2
tools/ioemu/a.out.h | 431
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/audio/alsaaudio.c | 981
+
tools/ioemu/audio/audio.c | 2047
++-
tools/ioemu/audio/audio.h | 114
tools/ioemu/audio/audio_int.h | 340
tools/ioemu/audio/audio_template.h | 565
tools/ioemu/audio/coreaudio.c | 564
tools/ioemu/audio/dsound_template.h | 282
tools/ioemu/audio/dsoundaudio.c | 1076
+
tools/ioemu/audio/fmodaudio.c | 683
+
tools/ioemu/audio/mixeng.c | 298
tools/ioemu/audio/mixeng.h | 26
tools/ioemu/audio/mixeng_template.h | 140
tools/ioemu/audio/noaudio.c | 170
tools/ioemu/audio/ossaudio.c | 707
-
tools/ioemu/audio/rate_template.h | 111
tools/ioemu/audio/sdlaudio.c | 423
tools/ioemu/audio/sys-queue.h | 241
tools/ioemu/audio/wavaudio.c | 208
tools/ioemu/block-bochs.c | 224
tools/ioemu/block-cloop.c | 12
tools/ioemu/block-cow.c | 7
tools/ioemu/block-dmg.c | 297
tools/ioemu/block-qcow.c | 53
tools/ioemu/block-vmdk.c | 200
tools/ioemu/block-vpc.c | 242
tools/ioemu/block-vvfat.c | 2807
++++
tools/ioemu/block.c | 272
tools/ioemu/block_int.h | 5
tools/ioemu/cocoa.m | 911
+
tools/ioemu/configure | 673
-
tools/ioemu/console.c | 396
tools/ioemu/cpu-all.h | 480
tools/ioemu/cpu-defs.h | 54
tools/ioemu/cpu-exec.c | 1480
++
tools/ioemu/dis-asm.h | 455
tools/ioemu/disas.c | 413
tools/ioemu/disas.h | 23
tools/ioemu/dyngen-exec.h | 257
tools/ioemu/dyngen-op.h | 9
tools/ioemu/dyngen.c | 2550
+++
tools/ioemu/dyngen.h | 429
tools/ioemu/elf.h | 1160
+
tools/ioemu/elf_ops.h | 205
tools/ioemu/exec-all.h | 252
tools/ioemu/exec.c | 2117
+++
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-macros.h | 720
+
tools/ioemu/fpu/softfloat-native.c | 363
tools/ioemu/fpu/softfloat-native.h | 359
tools/ioemu/fpu/softfloat-specialize.h | 464
tools/ioemu/fpu/softfloat.c | 5320
++++++++
tools/ioemu/fpu/softfloat.h | 398
tools/ioemu/gdbstub.c | 943
+
tools/ioemu/gdbstub.h | 12
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/hw/adb.c | 36
tools/ioemu/hw/adlib.c | 390
tools/ioemu/hw/apic.c | 1042
+
tools/ioemu/hw/arm_boot.c | 105
tools/ioemu/hw/arm_pic.c | 73
tools/ioemu/hw/arm_pic.h | 27
tools/ioemu/hw/arm_timer.c | 383
tools/ioemu/hw/cirrus_vga.c | 226
tools/ioemu/hw/cuda.c | 104
tools/ioemu/hw/dma.c | 4
tools/ioemu/hw/es1370.c | 1062
+
tools/ioemu/hw/esp.c | 747
+
tools/ioemu/hw/fdc.c | 58
tools/ioemu/hw/heathrow_pic.c | 168
tools/ioemu/hw/i8254.c | 63
tools/ioemu/hw/i8259.c | 212
tools/ioemu/hw/ide.c | 617
tools/ioemu/hw/integratorcp.c | 546
tools/ioemu/hw/iommu.c | 206
tools/ioemu/hw/lance.c | 292
tools/ioemu/hw/m48t59.c | 204
tools/ioemu/hw/m48t59.h | 10
tools/ioemu/hw/mips_r4k.c | 295
tools/ioemu/hw/ne2000.c | 219
tools/ioemu/hw/openpic.c | 22
tools/ioemu/hw/parallel.c | 183
tools/ioemu/hw/pc.c | 506
tools/ioemu/hw/pci.c | 721
-
tools/ioemu/hw/pckbd.c | 628
tools/ioemu/hw/pcspk.c | 147
tools/ioemu/hw/piix4acpi.c | 27
tools/ioemu/hw/pl011.c | 251
tools/ioemu/hw/pl050.c | 127
tools/ioemu/hw/pl080.c | 328
tools/ioemu/hw/pl110.c | 420
tools/ioemu/hw/pl110_template.h | 252
tools/ioemu/hw/pl190.c | 252
tools/ioemu/hw/ppc.c | 84
tools/ioemu/hw/ppc_chrp.c | 473
tools/ioemu/hw/ppc_prep.c | 216
tools/ioemu/hw/ps2.c | 566
tools/ioemu/hw/rtl8139.c | 2875
++++
tools/ioemu/hw/sb16.c | 333
tools/ioemu/hw/serial.c | 228
tools/ioemu/hw/sh7750.c | 836
+
tools/ioemu/hw/sh7750_regnames.c | 128
tools/ioemu/hw/sh7750_regnames.h | 6
tools/ioemu/hw/sh7750_regs.h | 1623
++
tools/ioemu/hw/shix.c | 111
tools/ioemu/hw/slavio_intctl.c | 400
tools/ioemu/hw/slavio_misc.c | 244
tools/ioemu/hw/slavio_serial.c | 545
tools/ioemu/hw/slavio_timer.c | 288
tools/ioemu/hw/smc91c111.c | 714
+
tools/ioemu/hw/sun4m.c | 339
tools/ioemu/hw/sun4u.c | 376
tools/ioemu/hw/tc58128.c | 181
tools/ioemu/hw/tcx.c | 407
tools/ioemu/hw/versatilepb.c | 271
tools/ioemu/hw/vga.c | 335
tools/ioemu/hw/vga_int.h | 2
tools/ioemu/i386-dis.c | 4143
++++++
tools/ioemu/i386-vl.ld | 140
tools/ioemu/i386.ld | 140
tools/ioemu/ia64.ld | 211
tools/ioemu/keymaps.c | 145
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 | 900
+
tools/ioemu/kqemu.h | 132
tools/ioemu/loader.c | 235
tools/ioemu/monitor.c | 1773
++
tools/ioemu/osdep.c | 129
tools/ioemu/osdep.h | 3
tools/ioemu/patches/acpi-poweroff-support | 26
tools/ioemu/patches/acpi-support | 58
tools/ioemu/patches/acpi-timer-support | 43
tools/ioemu/patches/domain-destroy | 24
tools/ioemu/patches/domain-reset | 45
tools/ioemu/patches/domain-timeoffset | 138
tools/ioemu/patches/hypervisor-pit | 48
tools/ioemu/patches/ide-hd-multithread | 75
tools/ioemu/patches/ioemu-ia64 | 86
tools/ioemu/patches/qemu-64bit | 95
tools/ioemu/patches/qemu-bugfixes | 56
tools/ioemu/patches/qemu-cleanup | 66
tools/ioemu/patches/qemu-dm | 399
tools/ioemu/patches/qemu-hvm-banner | 19
tools/ioemu/patches/qemu-infrastructure | 9
tools/ioemu/patches/qemu-init-vgabios | 17
tools/ioemu/patches/qemu-logging | 57
tools/ioemu/patches/qemu-no-apic | 42
tools/ioemu/patches/qemu-nobios | 48
tools/ioemu/patches/qemu-smp | 38
tools/ioemu/patches/qemu-target-i386-dm | 126
tools/ioemu/patches/qemu-timer | 37
tools/ioemu/patches/sdl-mouse-invisible-wall | 17
tools/ioemu/patches/serial-non-block | 23
tools/ioemu/patches/series | 37
tools/ioemu/patches/shadow-vram | 34
tools/ioemu/patches/shared-vram | 129
tools/ioemu/patches/support-xm-console | 38
tools/ioemu/patches/vnc-access-monitor-vt | 34
tools/ioemu/patches/vnc-cleanup | 65
tools/ioemu/patches/vnc-fixes | 336
tools/ioemu/patches/vnc-start-vncviewer | 69
tools/ioemu/patches/vnc-title-domain-name | 19
tools/ioemu/patches/xen-build | 179
tools/ioemu/patches/xen-domain-name | 64
tools/ioemu/patches/xen-domid | 38
tools/ioemu/patches/xen-mm | 63
tools/ioemu/patches/xen-network | 52
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/Makefile | 24
tools/ioemu/pc-bios/README | 17
tools/ioemu/pc-bios/bios.diff | 87
tools/ioemu/pc-bios/linux_boot.S | 29
tools/ioemu/pc-bios/ohw.diff | 1153
+
tools/ioemu/pc-bios/proll.patch | 939
+
tools/ioemu/pc-bios/vgabios.diff | 318
tools/ioemu/qemu-binfmt-conf.sh | 15
tools/ioemu/qemu-doc.texi | 1748
++
tools/ioemu/qemu-img.c | 17
tools/ioemu/qemu-img.texi | 126
tools/ioemu/qemu-tech.texi | 595
tools/ioemu/qemu_socket.h | 30
tools/ioemu/readline.c | 1
tools/ioemu/sdl.c | 239
tools/ioemu/sdl_keysym.h | 278
tools/ioemu/softmmu_exec.h | 65
tools/ioemu/softmmu_header.h | 385
tools/ioemu/softmmu_template.h | 313
tools/ioemu/tap-win32.c | 680
+
tools/ioemu/target-i386-dm/cpu.h | 90
tools/ioemu/target-i386-dm/exec-dm.c | 536
tools/ioemu/target-i386-dm/helper2.c | 270
tools/ioemu/target-i386-dm/i8259-dm.c | 107
tools/ioemu/target-i386-dm/qemu-ifup | 2
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/cpu.h | 653
+
tools/ioemu/target-i386/exec.h | 572
tools/ioemu/target-i386/helper.c | 3505
+++++
tools/ioemu/target-i386/helper2.c | 1028
+
tools/ioemu/target-i386/op.c | 2437
+++
tools/ioemu/target-i386/opreg_template.h | 190
tools/ioemu/target-i386/ops_mem.h | 156
tools/ioemu/target-i386/ops_sse.h | 1374
++
tools/ioemu/target-i386/ops_template.h | 597
tools/ioemu/target-i386/ops_template_mem.h | 483
tools/ioemu/target-i386/translate-copy.c | 1323
++
tools/ioemu/target-i386/translate.c | 6468
++++++++++
tools/ioemu/tests/.cvsignore | 23
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 | 92
tools/ioemu/tests/hello-arm.c | 113
tools/ioemu/tests/hello-i386.c | 26
tools/ioemu/tests/linux-test.c | 536
tools/ioemu/tests/qruncom.c | 327
tools/ioemu/tests/runcom.c | 195
tools/ioemu/tests/sha1.c | 242
tools/ioemu/tests/test-i386-code16.S | 79
tools/ioemu/tests/test-i386-muldiv.h | 76
tools/ioemu/tests/test-i386-shift.h | 187
tools/ioemu/tests/test-i386-vm86.S | 104
tools/ioemu/tests/test-i386.c | 2611
++++
tools/ioemu/tests/test-i386.h | 152
tools/ioemu/tests/test_path.c | 152
tools/ioemu/tests/testthread.c | 51
tools/ioemu/texi2pod.pl | 428
tools/ioemu/thunk.c | 2
tools/ioemu/translate-all.c | 311
tools/ioemu/translate-op.c | 37
tools/ioemu/vl.c | 4459
+++++-
tools/ioemu/vl.h | 540
tools/ioemu/vnc.c | 1649
+-
tools/ioemu/vnc_keysym.h | 275
tools/ioemu/vnchextile.h | 189
tools/libaio/COPYING | 515
tools/libaio/ChangeLog | 43
tools/libaio/INSTALL | 18
tools/libaio/Makefile | 40
tools/libaio/TODO | 4
tools/libaio/harness/Makefile | 37
tools/libaio/harness/README | 19
tools/libaio/harness/attic/0.t | 9
tools/libaio/harness/attic/1.t | 9
tools/libaio/harness/cases/10.t | 53
tools/libaio/harness/cases/11.t | 39
tools/libaio/harness/cases/12.t | 49
tools/libaio/harness/cases/13.t | 66
tools/libaio/harness/cases/14.t | 90
tools/libaio/harness/cases/2.t | 41
tools/libaio/harness/cases/3.t | 25
tools/libaio/harness/cases/4.t | 72
tools/libaio/harness/cases/5.t | 47
tools/libaio/harness/cases/6.t | 57
tools/libaio/harness/cases/7.t | 27
tools/libaio/harness/cases/8.t | 49
tools/libaio/harness/cases/aio_setup.h | 98
tools/libaio/harness/cases/common-7-8.h | 37
tools/libaio/harness/main.c | 39
tools/libaio/harness/runtests.sh | 19
tools/libaio/libaio.spec | 187
tools/libaio/man/aio.3 | 315
tools/libaio/man/aio_cancel.3 | 137
tools/libaio/man/aio_cancel64.3 | 50
tools/libaio/man/aio_error.3 | 81
tools/libaio/man/aio_error64.3 | 64
tools/libaio/man/aio_fsync.3 | 139
tools/libaio/man/aio_fsync64.3 | 51
tools/libaio/man/aio_init.3 | 96
tools/libaio/man/aio_read.3 | 146
tools/libaio/man/aio_read64.3 | 60
tools/libaio/man/aio_return.3 | 71
tools/libaio/man/aio_return64.3 | 51
tools/libaio/man/aio_suspend.3 | 123
tools/libaio/man/aio_suspend64.3 | 51
tools/libaio/man/aio_write.3 | 176
tools/libaio/man/aio_write64.3 | 61
tools/libaio/man/io.3 | 351
tools/libaio/man/io_cancel.1 | 21
tools/libaio/man/io_cancel.3 | 65
tools/libaio/man/io_destroy.1 | 17
tools/libaio/man/io_fsync.3 | 82
tools/libaio/man/io_getevents.1 | 29
tools/libaio/man/io_getevents.3 | 79
tools/libaio/man/io_prep_fsync.3 | 89
tools/libaio/man/io_prep_pread.3 | 79
tools/libaio/man/io_prep_pwrite.3 | 77
tools/libaio/man/io_queue_init.3 | 63
tools/libaio/man/io_queue_release.3 | 48
tools/libaio/man/io_queue_run.3 | 50
tools/libaio/man/io_queue_wait.3 | 56
tools/libaio/man/io_set_callback.3 | 44
tools/libaio/man/io_setup.1 | 15
tools/libaio/man/io_submit.1 | 109
tools/libaio/man/io_submit.3 | 135
tools/libaio/man/lio_listio.3 | 229
tools/libaio/man/lio_listio64.3 | 39
tools/libaio/src/Makefile | 64
tools/libaio/src/compat-0_1.c | 62
tools/libaio/src/io_cancel.c | 23
tools/libaio/src/io_destroy.c | 23
tools/libaio/src/io_getevents.c | 57
tools/libaio/src/io_queue_init.c | 33
tools/libaio/src/io_queue_release.c | 27
tools/libaio/src/io_queue_run.c | 39
tools/libaio/src/io_queue_wait.c | 31
tools/libaio/src/io_setup.c | 23
tools/libaio/src/io_submit.c | 23
tools/libaio/src/libaio.h | 222
tools/libaio/src/libaio.map | 22
tools/libaio/src/raw_syscall.c | 19
tools/libaio/src/syscall-alpha.h | 209
tools/libaio/src/syscall-i386.h | 72
tools/libaio/src/syscall-ia64.h | 45
tools/libaio/src/syscall-ppc.h | 94
tools/libaio/src/syscall-s390.h | 131
tools/libaio/src/syscall-x86_64.h | 63
tools/libaio/src/syscall.h | 27
tools/libaio/src/vsys_def.h | 24
tools/libxc/Makefile | 7
tools/libxc/ia64/Makefile | 5
tools/libxc/ia64/xc_ia64_hvm_build.c | 673
+
tools/libxc/ia64/xc_ia64_linux_restore.c | 320
tools/libxc/ia64/xc_ia64_linux_save.c | 509
tools/libxc/ia64/xc_ia64_stubs.c | 106
tools/libxc/xc_hvm_build.c | 32
tools/libxc/xc_linux_build.c | 67
tools/libxc/xc_private.c | 4
tools/libxc/xenctrl.h | 3
tools/misc/lomount/lomount.c | 430
tools/misc/xend | 7
tools/pygrub/README | 2
tools/python/xen/util/dictio.py | 50
tools/python/xen/util/pci.py | 97
tools/python/xen/util/security.py | 98
tools/python/xen/xend/XendDomain.py | 30
tools/python/xen/xend/XendDomainInfo.py | 9
tools/python/xen/xend/XendLogging.py | 2
tools/python/xen/xend/image.py | 54
tools/python/xen/xend/server/BlktapController.py | 14
tools/python/xen/xend/server/DevController.py | 7
tools/python/xen/xend/server/SrvDaemon.py | 2
tools/python/xen/xend/server/blkif.py | 12
tools/python/xen/xend/server/pciif.py | 7
tools/python/xen/xend/server/pciquirk.py | 145
tools/python/xen/xm/addlabel.py | 154
tools/python/xen/xm/create.py | 172
tools/python/xen/xm/dry-run.py | 56
tools/python/xen/xm/getlabel.py | 114
tools/python/xen/xm/main.py | 38
tools/python/xen/xm/resources.py | 56
tools/python/xen/xm/rmlabel.py | 118
tools/vtpm/Makefile | 43
tools/vtpm/tpm_emulator.patch | 1284
-
tools/vtpm/vtpm.patch | 1134
-
tools/vtpm_manager/Makefile | 14
tools/vtpm_manager/Rules.mk | 1
tools/vtpm_manager/crypto/sym_crypto.c | 17
tools/vtpm_manager/manager/dmictl.c | 114
tools/vtpm_manager/manager/migration.c | 307
tools/vtpm_manager/manager/securestorage.c | 85
tools/vtpm_manager/manager/vtpm_ipc.c | 2
tools/vtpm_manager/manager/vtpm_manager.c | 4
tools/vtpm_manager/manager/vtpm_manager.h | 16
tools/vtpm_manager/manager/vtpm_manager_handler.c | 21
tools/vtpm_manager/manager/vtpmd.c | 3
tools/vtpm_manager/manager/vtpmpriv.h | 39
tools/vtpm_manager/manager/vtsp.c | 68
tools/vtpm_manager/manager/vtsp.h | 3
tools/vtpm_manager/migration/Makefile | 39
tools/vtpm_manager/migration/vtpm_manager_if.c | 186
tools/vtpm_manager/migration/vtpm_migrator.h | 104
tools/vtpm_manager/migration/vtpm_migrator_if.c | 219
tools/vtpm_manager/migration/vtpm_migratorc.c | 211
tools/vtpm_manager/migration/vtpm_migratord.c | 202
tools/vtpm_manager/migration/vtpm_migratord_handler.c | 171
tools/vtpm_manager/tcs/tcs.c | 3
tools/vtpm_manager/tcs/transmit.c | 4
tools/vtpm_manager/util/buffer.c | 23
tools/vtpm_manager/util/buffer.h | 4
tools/vtpm_manager/util/log.h | 4
tools/vtpm_manager/util/tcg.h | 18
tools/xenmon/xenbaked.c | 269
tools/xenmon/xenmon.py | 52
tools/xenstat/libxenstat/src/xenstat.c | 1
tools/xenstore/Makefile | 24
tools/xm-test/configure.ac | 8
tools/xm-test/ramdisk/Makefile.am | 9
tools/xm-test/ramdisk/bin/create_disk_image | 33
tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py | 8
xen/Makefile | 2
xen/arch/ia64/Makefile | 14
xen/arch/ia64/asm-offsets.c | 11
xen/arch/ia64/linux-xen/Makefile | 2
xen/arch/ia64/linux-xen/README.origin | 2
xen/arch/ia64/linux-xen/entry.S | 15
xen/arch/ia64/linux-xen/iosapic.c | 8
xen/arch/ia64/linux-xen/mca.c | 1600
++
xen/arch/ia64/linux-xen/mca_asm.S | 970
+
xen/arch/ia64/linux-xen/minstate.h | 46
xen/arch/ia64/linux-xen/tlb.c | 4
xen/arch/ia64/linux-xen/unwind.c | 22
xen/arch/ia64/tools/README.RunVT | 95
xen/arch/ia64/vmx/mmio.c | 11
xen/arch/ia64/vmx/pal_emul.c | 591
xen/arch/ia64/vmx/vlsapic.c | 49
xen/arch/ia64/vmx/vmmu.c | 8
xen/arch/ia64/vmx/vmx_entry.S | 64
xen/arch/ia64/vmx/vmx_init.c | 80
xen/arch/ia64/vmx/vmx_interrupt.c | 2
xen/arch/ia64/vmx/vmx_ivt.S | 51
xen/arch/ia64/vmx/vmx_minstate.h | 51
xen/arch/ia64/vmx/vmx_phy_mode.c | 22
xen/arch/ia64/vmx/vmx_process.c | 35
xen/arch/ia64/vmx/vmx_support.c | 2
xen/arch/ia64/vmx/vmx_utility.c | 2
xen/arch/ia64/vmx/vmx_vcpu.c | 59
xen/arch/ia64/vmx/vmx_virt.c | 51
xen/arch/ia64/xen/Makefile | 1
xen/arch/ia64/xen/dom0_ops.c | 185
xen/arch/ia64/xen/dom_fw.c | 187
xen/arch/ia64/xen/domain.c | 408
xen/arch/ia64/xen/faults.c | 139
xen/arch/ia64/xen/fw_emul.c | 17
xen/arch/ia64/xen/hypercall.c | 11
xen/arch/ia64/xen/irq.c | 13
xen/arch/ia64/xen/ivt.S | 181
xen/arch/ia64/xen/mm.c | 171
xen/arch/ia64/xen/privop.c | 420
xen/arch/ia64/xen/privop_stat.c | 389
xen/arch/ia64/xen/regionreg.c | 19
xen/arch/ia64/xen/vcpu.c | 136
xen/arch/ia64/xen/vhpt.c | 24
xen/arch/ia64/xen/xenasm.S | 4
xen/arch/ia64/xen/xenmisc.c | 4
xen/arch/ia64/xen/xensetup.c | 12
xen/arch/powerpc/Makefile | 3
xen/arch/powerpc/setup.c | 36
xen/arch/powerpc/xen.lds.S | 239
xen/arch/x86/dom0_ops.c | 14
xen/arch/x86/hvm/i8254.c | 10
xen/arch/x86/hvm/intercept.c | 4
xen/arch/x86/hvm/io.c | 66
xen/arch/x86/hvm/platform.c | 19
xen/arch/x86/hvm/svm/intr.c | 1
xen/arch/x86/hvm/svm/svm.c | 130
xen/arch/x86/hvm/vmx/io.c | 1
xen/arch/x86/hvm/vmx/vmcs.c | 20
xen/arch/x86/hvm/vmx/vmx.c | 49
xen/arch/x86/irq.c | 17
xen/arch/x86/mm.c | 19
xen/arch/x86/shadow.c | 19
xen/arch/x86/shadow32.c | 24
xen/arch/x86/shadow_public.c | 74
xen/arch/x86/traps.c | 122
xen/arch/x86/x86_32/mm.c | 5
xen/arch/x86/x86_32/traps.c | 4
xen/arch/x86/x86_64/entry.S | 8
xen/arch/x86/x86_64/mm.c | 6
xen/arch/x86/x86_64/traps.c | 28
xen/arch/x86/x86_emulate.c | 19
xen/common/grant_table.c | 6
xen/common/memory.c | 2
xen/common/schedule.c | 7
xen/common/trace.c | 24
xen/include/asm-ia64/bundle.h | 231
xen/include/asm-ia64/config.h | 20
xen/include/asm-ia64/dom_fw.h | 4
xen/include/asm-ia64/domain.h | 122
xen/include/asm-ia64/iocap.h | 8
xen/include/asm-ia64/linux-xen/asm/README.origin | 1
xen/include/asm-ia64/linux-xen/asm/asmmacro.h | 119
xen/include/asm-ia64/linux-xen/asm/mca_asm.h | 4
xen/include/asm-ia64/linux-xen/asm/pgtable.h | 5
xen/include/asm-ia64/linux-xen/asm/system.h | 2
xen/include/asm-ia64/linux/asm/README.origin | 1
xen/include/asm-ia64/mm.h | 7
xen/include/asm-ia64/perfc_defn.h | 1
xen/include/asm-ia64/privop.h | 225
xen/include/asm-ia64/privop_stat.h | 66
xen/include/asm-ia64/regionreg.h | 1
xen/include/asm-ia64/shadow.h | 18
xen/include/asm-ia64/tlbflush.h | 6
xen/include/asm-ia64/vcpu.h | 25
xen/include/asm-ia64/vhpt.h | 3
xen/include/asm-ia64/vmx.h | 4
xen/include/asm-ia64/vmx_pal.h | 5
xen/include/asm-ia64/vmx_phy_mode.h | 1
xen/include/asm-ia64/vmx_vcpu.h | 1
xen/include/asm-ia64/vmx_vpd.h | 2
xen/include/asm-ia64/xenpage.h | 7
xen/include/asm-ia64/xensystem.h | 1
xen/include/asm-powerpc/mm.h | 5
xen/include/asm-powerpc/percpu.h | 22
xen/include/asm-x86/config.h | 12
xen/include/asm-x86/hvm/io.h | 4
xen/include/asm-x86/hvm/vcpu.h | 18
xen/include/asm-x86/hvm/vmx/vmx.h | 52
xen/include/asm-x86/hvm/vpit.h | 4
xen/include/asm-x86/mm.h | 5
xen/include/asm-x86/perfc_defn.h | 147
xen/include/asm-x86/processor.h | 3
xen/include/public/arch-ia64.h | 109
xen/include/public/dom0_ops.h | 14
xen/include/public/grant_table.h | 4
xen/include/public/trace.h | 1
xen/include/xen/irq.h | 2
xen/include/xen/perfc_defn.h | 136
670 files changed, 134737 insertions(+), 20765 deletions(-)
diff -r a75c389e4a7d -r 5ecfc7102cca .hgignore
--- a/.hgignore Tue Aug 01 16:42:48 2006 -0400
+++ b/.hgignore Tue Aug 01 16:51:03 2006 -0400
@@ -54,6 +54,7 @@
^extras/mini-os/h/xen-public$
^extras/mini-os/mini-os\..*$
^install/.*$
+^linux-[^/]*-native/.*$
^linux-[^/]*-xen/.*$
^linux-[^/]*-xen0/.*$
^linux-[^/]*-xenU/.*$
@@ -73,27 +74,11 @@
^tools/.*/TAGS$
^tools/.*/build/lib.*/.*\.py$
^tools/blktap/Makefile\.smh$
-^tools/blktap/blkcow$
-^tools/blktap/blkcowgnbd$
-^tools/blktap/blkcowimg$
-^tools/blktap/blkdump$
-^tools/blktap/blkgnbd$
-^tools/blktap/blkimg$
-^tools/blktap/bstest$
-^tools/blktap/parallax/blockstored$
-^tools/blktap/parallax/parallax$
-^tools/blktap/parallax/vdi_create$
-^tools/blktap/parallax/vdi_fill$
-^tools/blktap/parallax/vdi_list$
-^tools/blktap/parallax/vdi_snap$
-^tools/blktap/parallax/vdi_snap_delete$
-^tools/blktap/parallax/vdi_snap_list$
-^tools/blktap/parallax/vdi_tree$
-^tools/blktap/parallax/vdi_validate$
-^tools/blktap/ublkback/ublkback$
-^tools/blktap/vdi\.dot$
-^tools/blktap/vdi\.ps$
-^tools/blktap/xen/.*$
+^tools/blktap/drivers/blktapctrl$
+^tools/blktap/drivers/img2qcow$
+^tools/blktap/drivers/qcow-create$
+^tools/blktap/drivers/qcow2raw$
+^tools/blktap/drivers/tapdisk$
^tools/check/\..*$
^tools/console/xenconsole$
^tools/console/xenconsoled$
@@ -122,13 +107,21 @@
^tools/firmware/vmxassist/roms\.h$
^tools/firmware/vmxassist/vmxassist$
^tools/firmware/vmxassist/vmxloader$
-^tools/ioemu/config-host\..*$
-^tools/ioemu/keysym_adapter_sdl\.h$
-^tools/ioemu/keysym_adapter_vnc\.h$
-^tools/ioemu/target-.*/Makefile$
-^tools/ioemu/target-.*/config\..*$
-^tools/ioemu/target-.*/qemu-dm$
+^tools/ioemu/\.pc/.*$
+^tools/ioemu/config-host\.h$
+^tools/ioemu/config-host\.mak$
+^tools/ioemu/i386-dm/config\.h$
+^tools/ioemu/i386-dm/config\.mak$
+^tools/ioemu/i386-dm/qemu-dm$
+^tools/ioemu/qemu-doc\.html$
+^tools/ioemu/qemu-img\.1$
+^tools/ioemu/qemu-img\.pod$
+^tools/ioemu/qemu-tech\.html$
+^tools/ioemu/qemu\.1$
+^tools/ioemu/qemu\.pod$
^tools/libxc/xen/.*$
+^tools/libaio/src/.*\.ol$
+^tools/libaio/src/.*\.os$
^tools/misc/cpuperf/cpuperf-perfcntr$
^tools/misc/cpuperf/cpuperf-xen$
^tools/misc/lomount/lomount$
diff -r a75c389e4a7d -r 5ecfc7102cca Config.mk
--- a/Config.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/Config.mk Tue Aug 01 16:51:03 2006 -0400
@@ -36,6 +36,8 @@ CFLAGS ?= -O2 -fomit-frame-pointer
CFLAGS ?= -O2 -fomit-frame-pointer
CFLAGS += -DNDEBUG
else
+# Less than -O1 produces bad code and large stack frames
+CFLAGS ?= -O1 -fno-omit-frame-pointer
CFLAGS += -g
endif
diff -r a75c389e4a7d -r 5ecfc7102cca README
--- a/README Tue Aug 01 16:42:48 2006 -0400
+++ b/README Tue Aug 01 16:51:03 2006 -0400
@@ -91,6 +91,7 @@ provided by your Linux distributor:
* GNU Binutils
* Development install of zlib (e.g., zlib-dev)
* Development install of Python v2.3 or later (e.g., python-dev)
+ * Development install of curses (e.g., libncurses-dev)
* bridge-utils package (/sbin/brctl)
* iproute package (/sbin/ip)
* hotplug or udev
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/Rules.mk
--- a/buildconfigs/Rules.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/Rules.mk Tue Aug 01 16:51:03 2006 -0400
@@ -69,9 +69,6 @@ ref-%/.valid-ref: pristine-%/.valid-pris
touch $@ # update timestamp to avoid rebuild
endif
-%-prep:
- $(MAKE) -f buildconfigs/mk.$* prep
-
%-install:
$(MAKE) -f buildconfigs/mk.$* build
@@ -83,14 +80,19 @@ endif
%-build: %-dist
@: # do nothing
+%-prep: DESTDIR=$(DISTDIR)/install
+%-prep:
+ $(MAKE) -f buildconfigs/mk.$* prep
+
+%-config: DESTDIR=$(DISTDIR)/install
+%-config:
+ $(MAKE) -f buildconfigs/mk.$* config
+
%-delete:
$(MAKE) -f buildconfigs/mk.$* delete
%-clean:
$(MAKE) -f buildconfigs/mk.$* clean
-
-%-config:
- $(MAKE) -f buildconfigs/mk.$* config
linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref
rm -rf tmp-$@
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_ia64
--- a/buildconfigs/linux-defconfig_xen0_ia64 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_ia64 Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16.13-xen0
-# Mon May 22 14:46:31 2006
+# Fri Jun 30 12:59:19 2006
#
#
@@ -721,21 +721,10 @@ CONFIG_SERIAL_NONSTANDARD=y
#
# Serial drivers
#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
@@ -1516,8 +1505,16 @@ 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_BACKEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_DEVMEM is not set
+# CONFIG_XEN_REBOOT is not set
+# CONFIG_XEN_SMPBOOT is not set
CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
@@ -1525,19 +1522,21 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
CONFIG_XEN_PRIVILEGED_GUEST=y
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
CONFIG_XEN_BACKEND=y
# CONFIG_XEN_PCIDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_NETDEV_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_TPMDEV_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_DISABLE_SERIAL=y
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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_x86_32 Tue Aug 01 16:51:03 2006 -0400
@@ -1322,6 +1322,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=y
CONFIG_XEN_NETDEV_BACKEND=y
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen0_x86_64 Tue Aug 01 16:51:03 2006 -0400
@@ -1263,6 +1263,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=y
CONFIG_XEN_NETDEV_BACKEND=y
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_ia64
--- a/buildconfigs/linux-defconfig_xen_ia64 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_ia64 Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16.13-xen
-# Mon May 22 14:15:20 2006
+# Thu Jun 29 16:23:48 2006
#
#
@@ -727,21 +727,10 @@ CONFIG_SERIAL_NONSTANDARD=y
#
# Serial drivers
#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_ACPI=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
@@ -1522,8 +1511,16 @@ 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_BACKEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_DEVMEM is not set
+# CONFIG_XEN_REBOOT is not set
+# CONFIG_XEN_SMPBOOT is not set
CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
@@ -1531,19 +1528,21 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
CONFIG_XEN_PRIVILEGED_GUEST=y
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
CONFIG_XEN_BACKEND=y
# CONFIG_XEN_PCIDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_NETDEV_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_TPMDEV_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_DISABLE_SERIAL=y
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 a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_32 Tue Aug 01 16:51:03 2006 -0400
@@ -3023,6 +3023,7 @@ CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=y
CONFIG_XEN_NETDEV_BACKEND=y
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64 Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/linux-defconfig_xen_x86_64 Tue Aug 01 16:51:03 2006 -0400
@@ -2855,6 +2855,7 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=y
CONFIG_XEN_NETDEV_BACKEND=y
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
diff -r a75c389e4a7d -r 5ecfc7102cca buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen Tue Aug 01 16:42:48 2006 -0400
+++ b/buildconfigs/mk.linux-2.6-xen Tue Aug 01 16:51:03 2006 -0400
@@ -4,6 +4,11 @@ EXTRAVERSION ?= xen
EXTRAVERSION ?= xen
LINUX_DIR = linux-$(LINUX_VER)-$(EXTRAVERSION)
+
+IMAGE_TARGET ?= vmlinuz
+INSTALL_BOOT_PATH ?= $(DESTDIR)
+
+LINUX_VER3 := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
include buildconfigs/Rules.mk
@@ -14,8 +19,9 @@ build: $(LINUX_DIR)/include/linux/autoco
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH)
INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
fi
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR)
vmlinuz
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR)
install
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR)
$(IMAGE_TARGET)
+ mkdir -p $(INSTALL_BOOT_PATH)
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH)
INSTALL_PATH=$(INSTALL_BOOT_PATH) install
$(LINUX_DIR)/include/linux/autoconf.h: ref-linux-$(LINUX_VER)/.valid-ref
rm -rf $(LINUX_DIR)
@@ -25,10 +31,9 @@ build: $(LINUX_DIR)/include/linux/autoco
LINUX_ARCH=$(LINUX_ARCH) bash ./mkbuildtree ../$(LINUX_DIR) )
# Re-use config from install dir if one exits else use default config
CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p'
$(LINUX_DIR)/Makefile); \
- [ -r
$(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
- cp
$(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION)
$(LINUX_DIR)/.config \
- || cp
buildconfigs/linux-defconfig_$(EXTRAVERSION)_$(XEN_TARGET_ARCH)$(XEN_SYSTYPE) \
- $(LINUX_DIR)/.config
+ [ -r
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
+ cp
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION-$(EXTRAVERSION)
$(LINUX_DIR)/.config \
+ || sh buildconfigs/create_config.sh $(LINUX_DIR)/.config
$(EXTRAVERSION) $(XEN_TARGET_ARCH) $(XEN_SYSTYPE)
# See if we need to munge config to enable PAE
$(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk
config-update-pae
# Patch kernel Makefile to set EXTRAVERSION
diff -r a75c389e4a7d -r 5ecfc7102cca config/ia64.mk
--- a/config/ia64.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/config/ia64.mk Tue Aug 01 16:51:03 2006 -0400
@@ -1,4 +1,5 @@ CONFIG_IA64 := y
CONFIG_IA64 := y
CONFIG_IOEMU := y
+CONFIG_XCUTILS := y
LIBDIR := lib
diff -r a75c389e4a7d -r 5ecfc7102cca config/x86_32.mk
--- a/config/x86_32.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/config/x86_32.mk Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@ CONFIG_X86 := y
CONFIG_X86 := y
-CONFIG_PLAN9 := y
CONFIG_HVM := y
CONFIG_MIGRATE := y
+CONFIG_XCUTILS := y
CONFIG_IOEMU := y
CONFIG_MBOOTPACK := y
diff -r a75c389e4a7d -r 5ecfc7102cca config/x86_64.mk
--- a/config/x86_64.mk Tue Aug 01 16:42:48 2006 -0400
+++ b/config/x86_64.mk Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@ CONFIG_X86 := y
CONFIG_X86 := y
-CONFIG_PLAN9 := y
CONFIG_HVM := y
CONFIG_MIGRATE := y
+CONFIG_XCUTILS := y
CONFIG_IOEMU := y
CONFIG_MBOOTPACK := y
diff -r a75c389e4a7d -r 5ecfc7102cca docs/src/user.tex
--- a/docs/src/user.tex Tue Aug 01 16:42:48 2006 -0400
+++ b/docs/src/user.tex Tue Aug 01 16:51:03 2006 -0400
@@ -1287,8 +1287,8 @@ backend domain. The PCI Backend appears
backend domain. The PCI Backend appears to the Linux kernel as a regular PCI
device driver. The PCI Backend ensures that no other device driver loads
for the devices by binding itself as the device driver for those devices.
-PCI devices are identified by hexadecimal slot/funciton numbers (on Linux,
-use \path{lspci} to determine slot/funciton numbers of your devices) and
+PCI devices are identified by hexadecimal slot/function numbers (on Linux,
+use \path{lspci} to determine slot/function numbers of your devices) and
can be specified with or without the PCI domain: \\
\centerline{ {\tt ({\em bus}:{\em slot}.{\em func})} example {\tt (02:1d.3)}}
\\
\centerline{ {\tt ({\em domain}:{\em bus}:{\em slot}.{\em func})} example
{\tt (0000:02:1d.3)}} \\
@@ -1344,6 +1344,50 @@ Note that the "-n" option in the example
Note that the "-n" option in the example is important as it causes echo to not
output a new-line.
+\subsubsection{PCI Backend Configuration - User-space Quirks}
+Quirky devices (such as the Broadcom Tigon 3) may need write access to their
+configuration space registers. Xen can be instructed to allow specified PCI
+devices write access to specific configuration space registers. The policy may
+be found in:
+
+\centerline{ \path{/etc/xen/xend-pci-quirks.sxp} }
+
+The policy file is heavily commented and is intended to provide enough
+documentation for developers to extend it.
+
+\subsubsection{PCI Backend Configuration - Permissive Flag}
+If the user-space quirks approach doesn't meet your needs you may want to
enable
+the permissive flag for that device. To do so, first get the PCI domain, bus,
+slot, and function information from dom0 via \path{lspci}. Then augment the
+user-space policy for permissive devices. The permissive policy can be found
+in:
+
+\centerline{ \path{/etc/xen/xend-pci-permissive.sxp} }
+
+Currently, the only way to reset the permissive flag is to unbind the device
+from the PCI Backend driver.
+
+\subsubsection{PCI Backend - Checking Status}
+There two important sysfs nodes that provide a mechanism to view specifics on
+quirks and permissive devices:
+\begin{description}
+\item \path{/sys/bus/drivers/pciback/permissive} \\
+ Use \path{cat} on this file to view a list of permissive slots.
+\item \path{/sys/bus/drivers/pciback/quirks} \\
+ Use \path{cat} on this file view a hierarchical view of devices bound to the
+PCI backend, their PCI vendor/device ID, and any quirks that are associated
with
+that particular slot.
+\end{description}
+
+You may notice that every device bound to the PCI backend has 17 quirks
standard
+"quirks" regardless of \path{xend-pci-quirks.sxp}. These default entries are
+necessary to support interactions between the PCI bus manager and the device
bound
+to it. Even non-quirky devices should have these standard entries.
+
+In this case, preference was given to accuracy over aesthetics by choosing to
+show the standard quirks in the quirks list rather than hide them from the
+inquiring user
+
\subsubsection{PCI Frontend Configuration}
To configure a domU to receive a PCI device:
@@ -1374,8 +1418,136 @@ To configure a domU to receive a PCI dev
%% There are two possible types of privileges: IO privileges and
%% administration privileges.
-
-
+\section{Support for virtual Trusted Platform Module (vTPM)}
+\label{ss:vtpm}
+
+Paravirtualized domains can be given access to a virtualized version
+of a TPM. This enables applications in these domains to use the services
+of the TPM device for example through a TSS stack
+\footnote{Trousers TSS stack: http://sourceforge.net/projects/trousers}.
+The Xen source repository provides the necessary software components to
+enable virtual TPM access. Support is provided through several
+different pieces. First, a TPM emulator has been modified to provide TPM's
+functionality for the virtual TPM subsystem. Second, a virtual TPM Manager
+coordinates the virtual TPMs efforts, manages their creation, and provides
+protected key storage using the TPM. Third, a device driver pair providing
+a TPM front- and backend is available for XenLinux to deliver TPM commands
+from the domain to the virtual TPM manager, which dispatches it to a
+software TPM. Since the TPM Manager relies on a HW TPM for protected key
+storage, therefore this subsystem requires a Linux-supported hardware TPM.
+For development purposes, a TPM emulator is available for use on non-TPM
+enabled platforms.
+
+\subsubsection{Compile-Time Setup}
+To enable access to the virtual TPM, the virtual TPM backend driver must
+be compiled for a privileged domain (e.g. domain 0). Using the XenLinux
+configuration, the necessary driver can be selected in the Xen configuration
+section. Unless the driver has been compiled into the kernel, its module
+must be activated using the following command:
+
+\begin{verbatim}
+modprobe tpmbk
+\end{verbatim}
+
+Similarly, the TPM frontend driver must be compiled for the kernel trying
+to use TPM functionality. Its driver can be selected in the kernel
+configuration section Device Driver / Character Devices / TPM Devices.
+Along with that the TPM driver for the built-in TPM must be selected.
+If the virtual TPM driver has been compiled as module, it
+must be activated using the following command:
+
+\begin{verbatim}
+modprobe tpm_xenu
+\end{verbatim}
+
+Furthermore, it is necessary to build the virtual TPM manager and software
+TPM by making changes to entries in Xen build configuration files.
+The following entry in the file Config.mk in the Xen root source
+directory must be made:
+
+\begin{verbatim}
+VTPM_TOOLS ?= y
+\end{verbatim}
+
+After a build of the Xen tree and a reboot of the machine, the TPM backend
+drive must be loaded. Once loaded, the virtual TPM manager daemon
+must be started before TPM-enabled guest domains may be launched.
+To enable being the destination of a virtual TPM Migration, the virtual TPM
+migration daemon must also be loaded.
+
+\begin{verbatim}
+vtpm_managerd
+\end{verbatim}
+\begin{verbatim}
+vtpm_migratord
+\end{verbatim}
+
+Once the VTPM manager is running, the VTPM can be accessed by loading the
+front end driver in a guest domain.
+
+\subsubsection{Development and Testing TPM Emulator}
+For development and testing on non-TPM enabled platforms, a TPM emulator
+can be used in replacement of a platform TPM. First, the entry in the file
+tools/vtpm/Rules.mk must look as follows:
+
+\begin{verbatim}
+BUILD_EMULATOR = y
+\end{verbatim}
+
+Second, the entry in the file tool/vtpm\_manager/Rules.mk must be uncommented
+as follows:
+
+\begin{verbatim}
+# TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifos
+CFLAGS += -DDUMMY_TPM
+\end{verbatim}
+
+Before starting the virtual TPM Manager, start the emulator by executing
+the following in dom0:
+
+\begin{verbatim}
+tpm_emulator clear
+\end{verbatim}
+
+\subsubsection{vTPM Frontend Configuration}
+To provide TPM functionality to a user domain, a line must be added to
+the virtual TPM configuration file using the following format:
+
+\begin{verbatim}
+vtpm = ['instance=<instance number>, backend=<domain id>']
+\end{verbatim}
+
+The { \it instance number} reflects the preferred virtual TPM instance
+to associate with the domain. If the selected instance is
+already associated with another domain, the system will automatically
+select the next available instance. An instance number greater than
+zero must be provided. It is possible to omit the instance
+parameter from the configuration file.
+
+The {\it domain id} provides the ID of the domain where the
+virtual TPM backend driver and virtual TPM are running in. It should
+currently always be set to '0'.
+
+
+Examples for valid vtpm entries in the configuration file are
+
+\begin{verbatim}
+ vtpm = ['instance=1, backend=0']
+\end{verbatim}
+and
+\begin{verbatim}
+ vtpm = ['backend=0'].
+\end{verbatim}
+
+\subsubsection{Using the virtual TPM}
+
+Access to TPM functionality is provided by the virtual TPM frontend driver.
+Similar to existing hardware TPM drivers, this driver provides basic TPM
+status information through the {\it sysfs} filesystem. In a Xen user domain
+the sysfs entries can be found in /sys/devices/xen/vtpm-0.
+
+Commands can be sent to the virtual TPM instance using the character
+device /dev/tpm0 (major 10, minor 224).
% Chapter Storage and FileSytem Management
\chapter{Storage and File System Management}
diff -r a75c389e4a7d -r 5ecfc7102cca extras/mini-os/mm.c
--- a/extras/mini-os/mm.c Tue Aug 01 16:42:48 2006 -0400
+++ b/extras/mini-os/mm.c Tue Aug 01 16:51:03 2006 -0400
@@ -687,7 +687,7 @@ void *map_frames(unsigned long *f, unsig
/* Find a run of n contiguous frames */
for (x = 0; x <= 1024 - n; x += y + 1) {
for (y = 0; y < n; y++)
- if (demand_map_pgt[y] & _PAGE_PRESENT)
+ if (demand_map_pgt[x+y] & _PAGE_PRESENT)
break;
if (y == n)
break;
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Aug 01 16:51:03
2006 -0400
@@ -958,11 +958,17 @@ u64 jiffies_to_st(unsigned long j)
do {
seq = read_seqbegin(&xtime_lock);
delta = j - jiffies;
- /* NB. The next check can trigger in some wrap-around cases,
- * but that's ok: we'll just end up with a shorter timeout. */
- if (delta < 1)
- delta = 1;
- st = processed_system_time + (delta * (u64)NS_PER_TICK);
+ if (delta < 1) {
+ /* Triggers in some wrap-around cases, but that's okay:
+ * we just end up with a shorter timeout. */
+ st = processed_system_time + NS_PER_TICK;
+ } else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
+ /* Very long timeout means there is no pending timer.
+ * We indicate this to Xen by passing zero timeout. */
+ st = 0;
+ } else {
+ st = processed_system_time + delta * (u64)NS_PER_TICK;
+ }
} while (read_seqretry(&xtime_lock, seq));
return st;
@@ -989,14 +995,15 @@ static void stop_hz_timer(void)
smp_mb();
- /* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */
+ /* Leave ourselves in tick mode if rcu or softirq or timer pending. */
if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
(j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
cpu_clear(cpu, nohz_cpu_mask);
j = jiffies + 1;
}
- BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
+ if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
+ BUG();
}
static void start_hz_timer(void)
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Tue Aug 01 16:51:03
2006 -0400
@@ -266,6 +266,7 @@ static void contiguous_bitmap_clear(
/* Protected by balloon_lock. */
#define MAX_CONTIG_ORDER 9 /* 2MB */
static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
+static multicall_entry_t cr_mcl[1<<MAX_CONTIG_ORDER];
/* Ensure multi-page extents are contiguous in machine memory. */
int xen_create_contiguous_region(
@@ -310,12 +311,13 @@ int xen_create_contiguous_region(
/* 1. Zap current PTEs, remembering MFNs. */
for (i = 0; i < (1UL<<order); i++) {
in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
- if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
- __pte_ma(0), 0))
- BUG();
+ MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ __pte_ma(0), 0);
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
INVALID_P2M_ENTRY);
}
+ if (HYPERVISOR_multicall(cr_mcl, i))
+ BUG();
/* 2. Get a new contiguous memory extent. */
out_frame = __pa(vstart) >> PAGE_SHIFT;
@@ -343,15 +345,16 @@ int xen_create_contiguous_region(
/* 3. Map the new extent in place of old pages. */
for (i = 0; i < (1UL<<order); i++) {
frame = success ? (out_frame + i) : in_frames[i];
- if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
- pfn_pte_ma(frame,
- PAGE_KERNEL),
- 0))
- BUG();
+ MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ pfn_pte_ma(frame, PAGE_KERNEL), 0);
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
}
- flush_tlb_all();
+ cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+ ? UVMF_TLB_FLUSH|UVMF_ALL
+ : UVMF_INVLPG|UVMF_ALL;
+ if (HYPERVISOR_multicall(cr_mcl, i))
+ BUG();
if (success)
contiguous_bitmap_set(__pa(vstart) >> PAGE_SHIFT,
@@ -402,13 +405,14 @@ void xen_destroy_contiguous_region(unsig
/* 2. Zap current PTEs. */
for (i = 0; i < (1UL<<order); i++) {
- if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
- __pte_ma(0), 0))
- BUG();
+ MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ __pte_ma(0), 0);
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
INVALID_P2M_ENTRY);
out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
}
+ if (HYPERVISOR_multicall(cr_mcl, i))
+ BUG();
/* 3. Do the exchange for non-contiguous MFNs. */
rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
@@ -429,15 +433,16 @@ void xen_destroy_contiguous_region(unsig
/* 4. Map new pages in place of old pages. */
for (i = 0; i < (1UL<<order); i++) {
frame = success ? out_frames[i] : (in_frame + i);
- if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
- pfn_pte_ma(frame,
- PAGE_KERNEL),
- 0))
- BUG();
+ MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ pfn_pte_ma(frame, PAGE_KERNEL), 0);
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
}
- flush_tlb_all();
+ cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+ ? UVMF_TLB_FLUSH|UVMF_ALL
+ : UVMF_INVLPG|UVMF_ALL;
+ if (HYPERVISOR_multicall(cr_mcl, i))
+ BUG();
balloon_unlock(flags);
}
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Tue Aug 01 16:51:03
2006 -0400
@@ -652,8 +652,13 @@ void mm_pin_all(void)
void mm_pin_all(void)
{
struct page *page;
+
+ /* Only pgds on the pgd_list please: none hidden in the slab cache. */
+ kmem_cache_shrink(pgd_cache);
+
if (xen_feature(XENFEAT_writable_page_tables))
return;
+
for (page = pgd_list; page; page = (struct page *)page->index) {
if (!test_bit(PG_pinned, &page->flags))
__pgd_pin((pgd_t *)page_address(page));
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Aug 01
16:51:03 2006 -0400
@@ -29,6 +29,7 @@
#include <xen/interface/xen.h>
#include <xen/interface/xenoprof.h>
#include <../../../drivers/oprofile/cpu_buffer.h>
+#include <../../../drivers/oprofile/event_buffer.h>
static int xenoprof_start(void);
static void xenoprof_stop(void);
@@ -151,16 +152,27 @@ static void xenoprof_handle_passive(void
static void xenoprof_handle_passive(void)
{
int i, j;
-
- for (i = 0; i < pdomains; i++)
+ int flag_domain, flag_switch = 0;
+
+ for (i = 0; i < pdomains; i++) {
+ flag_domain = 0;
for (j = 0; j < passive_domains[i].nbuf; j++) {
xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
if (buf->event_head == buf->event_tail)
continue;
- oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_START,
passive_domains[i].domain_id);
+ if (!flag_domain) {
+ if
(!oprofile_add_domain_switch(passive_domains[i].
+ domain_id))
+ goto done;
+ flag_domain = 1;
+ }
xenoprof_add_pc(buf, 1);
- oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_STOP,
passive_domains[i].domain_id);
- }
+ flag_switch = 1;
+ }
+ }
+done:
+ if (flag_switch)
+ oprofile_add_domain_switch(COORDINATOR_DOMAIN);
}
static irqreturn_t
@@ -177,6 +189,7 @@ xenoprof_ovf_interrupt(int irq, void * d
if (is_primary && !test_and_set_bit(0, &flag)) {
xenoprof_handle_passive();
+ smp_mb__before_clear_bit();
clear_bit(0, &flag);
}
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/ia64/Kconfig
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Tue Aug 01 16:51:03 2006 -0400
@@ -70,6 +70,13 @@ config XEN_IA64_DOM0_NON_VP
default y
help
dom0 P=M model
+
+config XEN_IA64_VDSO_PARAVIRT
+ bool
+ depends on XEN && !ITANIUM
+ default y
+ help
+ vDSO paravirtualization
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
@@ -518,7 +525,7 @@ config XEN_DEVMEM
default n
config XEN_REBOOT
- default n
+ default y
config XEN_SMPBOOT
default n
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c Tue Aug 01 16:51:03
2006 -0400
@@ -31,6 +31,9 @@
#include <linux/smp_lock.h>
#include <linux/threads.h>
#include <linux/bitops.h>
+#ifdef CONFIG_XEN
+#include <linux/cpu.h>
+#endif
#include <asm/delay.h>
#include <asm/intrinsics.h>
@@ -235,6 +238,9 @@ static struct irqaction ipi_irqaction =
#include <xen/evtchn.h>
#include <xen/interface/callback.h>
+static DEFINE_PER_CPU(int, timer_irq) = -1;
+static DEFINE_PER_CPU(int, ipi_irq) = -1;
+static DEFINE_PER_CPU(int, resched_irq) = -1;
static char timer_name[NR_CPUS][15];
static char ipi_name[NR_CPUS][15];
static char resched_name[NR_CPUS][15];
@@ -252,6 +258,7 @@ static unsigned short saved_irq_cnt = 0;
static unsigned short saved_irq_cnt = 0;
static int xen_slab_ready = 0;
+#ifdef CONFIG_SMP
/* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ,
* it ends up to issue several memory accesses upon percpu data and
* thus adds unnecessary traffic to other paths.
@@ -268,6 +275,7 @@ static struct irqaction resched_irqactio
.flags = SA_INTERRUPT,
.name = "RESCHED"
};
+#endif
/*
* This is xen version percpu irq registration, which needs bind
@@ -294,6 +302,7 @@ xen_register_percpu_irq (unsigned int ir
ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
action->handler, action->flags,
timer_name[cpu], action->dev_id);
+ per_cpu(timer_irq,cpu) = ret;
printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq
(%d)\n", timer_name[cpu], ret);
break;
case IA64_IPI_RESCHEDULE:
@@ -301,6 +310,7 @@ xen_register_percpu_irq (unsigned int ir
ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu,
action->handler, action->flags,
resched_name[cpu], action->dev_id);
+ per_cpu(resched_irq,cpu) = ret;
printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to
xen irq (%d)\n", resched_name[cpu], ret);
break;
case IA64_IPI_VECTOR:
@@ -308,6 +318,7 @@ xen_register_percpu_irq (unsigned int ir
ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu,
action->handler, action->flags,
ipi_name[cpu], action->dev_id);
+ per_cpu(ipi_irq,cpu) = ret;
printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq
(%d)\n", ipi_name[cpu], ret);
break;
case IA64_SPURIOUS_INT_VECTOR:
@@ -343,7 +354,7 @@ xen_bind_early_percpu_irq (void)
*/
for (i = 0; i < late_irq_cnt; i++)
xen_register_percpu_irq(saved_percpu_irqs[i].irq,
- saved_percpu_irqs[i].action, 0);
+ saved_percpu_irqs[i].action, 0);
}
/* FIXME: There's no obvious point to check whether slab is ready. So
@@ -352,6 +363,38 @@ extern void (*late_time_init)(void);
extern void (*late_time_init)(void);
extern char xen_event_callback;
extern void xen_init_IRQ(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __devinit
+unbind_evtchn_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ if (action == CPU_DEAD) {
+ /* Unregister evtchn. */
+ if (per_cpu(ipi_irq,cpu) >= 0) {
+ unbind_from_irqhandler (per_cpu(ipi_irq, cpu), NULL);
+ per_cpu(ipi_irq, cpu) = -1;
+ }
+ if (per_cpu(resched_irq,cpu) >= 0) {
+ unbind_from_irqhandler (per_cpu(resched_irq, cpu),
+ NULL);
+ per_cpu(resched_irq, cpu) = -1;
+ }
+ if (per_cpu(timer_irq,cpu) >= 0) {
+ unbind_from_irqhandler (per_cpu(timer_irq, cpu), NULL);
+ per_cpu(timer_irq, cpu) = -1;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block unbind_evtchn_notifier = {
+ .notifier_call = unbind_evtchn_callback,
+ .priority = 0
+};
+#endif
DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
void xen_smp_intr_init(void)
@@ -363,21 +406,22 @@ void xen_smp_intr_init(void)
.type = CALLBACKTYPE_event,
.address = (unsigned long)&xen_event_callback,
};
- static cpumask_t registered_cpumask;
-
- if (!cpu)
+
+ if (cpu == 0) {
+ /* Initialization was already done for boot cpu. */
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Register the notifier only once. */
+ register_cpu_notifier(&unbind_evtchn_notifier);
+#endif
return;
+ }
/* This should be piggyback when setup vcpu guest context */
BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
- if (!cpu_isset(cpu, registered_cpumask)) {
- cpu_set(cpu, registered_cpumask);
- for (i = 0; i < saved_irq_cnt; i++)
- xen_register_percpu_irq(saved_percpu_irqs[i].irq,
- saved_percpu_irqs[i].action,
- 0);
- }
+ for (i = 0; i < saved_irq_cnt; i++)
+ xen_register_percpu_irq(saved_percpu_irqs[i].irq,
+ saved_percpu_irqs[i].action, 0);
#endif /* CONFIG_SMP */
}
#endif /* CONFIG_XEN */
@@ -388,12 +432,13 @@ register_percpu_irq (ia64_vector vec, st
irq_desc_t *desc;
unsigned int irq;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen())
+ return xen_register_percpu_irq(vec, action, 1);
+#endif
+
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vec) {
-#ifdef CONFIG_XEN
- if (is_running_on_xen())
- return xen_register_percpu_irq(vec, action, 1);
-#endif
desc = irq_descp(irq);
desc->status |= IRQ_PER_CPU;
desc->handler = &irq_type_ia64_lsapic;
@@ -441,6 +486,7 @@ ia64_send_ipi (int cpu, int vector, int
if (is_running_on_xen()) {
int irq = -1;
+#ifdef CONFIG_SMP
/* TODO: we need to call vcpu_up here */
if (unlikely(vector == ap_wakeup_vector)) {
extern void xen_send_ipi (int cpu, int vec);
@@ -448,6 +494,7 @@ ia64_send_ipi (int cpu, int vector, int
//vcpu_prepare_and_up(cpu);
return;
}
+#endif
switch(vector) {
case IA64_IPI_VECTOR:
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Tue Aug 01 16:51:03
2006 -0400
@@ -75,6 +75,20 @@ EXPORT_SYMBOL(__per_cpu_offset);
EXPORT_SYMBOL(__per_cpu_offset);
#endif
+#ifdef CONFIG_XEN
+static int
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ HYPERVISOR_shutdown(SHUTDOWN_crash);
+ /* we're never actually going to get here... */
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block xen_panic_block = {
+ xen_panic_event, NULL, 0 /* try to go last */
+};
+#endif
+
extern void ia64_setup_printk_clock(void);
DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
@@ -418,8 +432,11 @@ setup_arch (char **cmdline_p)
unw_init();
#ifdef CONFIG_XEN
- if (is_running_on_xen())
+ if (is_running_on_xen()) {
setup_xen_features();
+ /* Register a call for panic conditions. */
+ notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+ }
#endif
ia64_patch_vtop((u64) __start___vtop_patchlist, (u64)
__end___vtop_patchlist);
@@ -523,15 +540,14 @@ setup_arch (char **cmdline_p)
shared_info_t *s = HYPERVISOR_shared_info;
xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
- xen_start_info->flags = s->arch.flags;
printk("Running on Xen! start_info_pfn=0x%lx nr_pages=%ld "
"flags=0x%x\n", s->arch.start_info_pfn,
xen_start_info->nr_pages, xen_start_info->flags);
/* xen_start_info isn't setup yet, get the flags manually */
- if (s->arch.flags & SIF_INITDOMAIN) {
- if (!(s->arch.flags & SIF_PRIVILEGED))
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
panic("Xen granted us console access "
"but not privileged status");
} else {
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Tue Aug 01 16:51:03
2006 -0400
@@ -351,3 +351,59 @@ GLOBAL_ENTRY(xen_send_ipi)
br.ret.sptk.many rp
;;
END(xen_send_ipi)
+
+#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
+// Those are vdso specialized.
+// In fsys mode, call, ret can't be used.
+GLOBAL_ENTRY(xen_rsm_be_i)
+ ld8 r22=[r22]
+ ;;
+ st1 [r22]=r20
+ st4 [r23]=r0
+ XEN_HYPER_RSM_BE
+ st4 [r23]=r20
+ brl.cond.sptk .vdso_rsm_be_i_ret
+ ;;
+END(xen_rsm_be_i)
+
+GLOBAL_ENTRY(xen_get_psr)
+ mov r31=r8
+ mov r25=IA64_PSR_IC
+ st4 [r23]=r0
+ XEN_HYPER_GET_PSR
+ ;;
+ st4 [r23]=r20
+ or r29=r8,r25 // vpsr.ic was cleared for hyperprivop
+ mov r8=r31
+ brl.cond.sptk .vdso_get_psr_ret
+ ;;
+END(xen_get_psr)
+
+GLOBAL_ENTRY(xen_ssm_i_0)
+ st4 [r22]=r20
+ ld4 r25=[r24]
+ ;;
+ cmp.ne.unc p11,p0=r0, r25
+ ;;
+(p11) st4 [r22]=r0
+(p11) st4 [r23]=r0
+(p11) XEN_HYPER_SSM_I
+
+ brl.cond.sptk .vdso_ssm_i_0_ret
+ ;;
+END(xen_ssm_i_0)
+
+GLOBAL_ENTRY(xen_ssm_i_1)
+ st4 [r22]=r20
+ ld4 r25=[r24]
+ ;;
+ cmp.ne.unc p11,p0=r0, r25
+ ;;
+(p11) st4 [r22]=r0
+(p11) st4 [r23]=r0
+(p11) XEN_HYPER_SSM_I
+ ;;
+ brl.cond.sptk .vdso_ssm_i_1_ret
+ ;;
+END(xen_ssm_i_1)
+#endif
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Tue Aug 01 16:51:03
2006 -0400
@@ -198,7 +198,7 @@ __xen_create_contiguous_region(unsigned
.nr_exchanged = 0
};
- if (order > MAX_CONTIG_ORDER)
+ if (unlikely(order > MAX_CONTIG_ORDER))
return -ENOMEM;
set_xen_guest_handle(exchange.in.extent_start, in_frames);
@@ -299,7 +299,7 @@ __xen_destroy_contiguous_region(unsigned
if (!test_bit(start_gpfn, contiguous_bitmap))
return;
- if (order > MAX_CONTIG_ORDER)
+ if (unlikely(order > MAX_CONTIG_ORDER))
return;
set_xen_guest_handle(exchange.in.extent_start, &in_frame);
@@ -547,8 +547,10 @@ xen_ia64_privcmd_entry_mmap(struct vm_ar
unsigned long gpfn;
unsigned long flags;
- BUG_ON((addr & ~PAGE_MASK) != 0);
- BUG_ON(mfn == INVALID_MFN);
+ if ((addr & ~PAGE_MASK) != 0 || mfn == INVALID_MFN) {
+ error = -EINVAL;
+ goto out;
+ }
if (entry->gpfn != INVALID_GPFN) {
error = -EBUSY;
@@ -793,3 +795,13 @@ direct_remap_pfn_range(struct vm_area_st
return error;
}
+
+/* Called after suspend, to resume time. */
+void
+time_resume(void)
+{
+ extern void ia64_cpu_local_tick(void);
+
+ /* Just trigger a tick. */
+ ia64_cpu_local_tick();
+}
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/ia64/xen/util.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c Tue Aug 01 16:51:03 2006 -0400
@@ -71,6 +71,9 @@ void free_vm_area(struct vm_struct *area
unsigned int order = get_order(area->size);
unsigned long i;
+ /* xenbus_map_ring_valloc overrides this field! */
+ area->phys_addr = __pa(area->addr);
+
// This area is used for foreign page mappping.
// So underlying machine page may not be assigned.
for (i = 0; i < (1 << order); i++) {
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S Tue Aug 01 16:51:03
2006 -0400
@@ -33,3 +33,23 @@ GLOBAL_ENTRY(early_xen_setup)
br.ret.sptk.many rp
;;
END(early_xen_setup)
+
+#include <xen/interface/xen.h>
+
+/* Stub for suspend.
+ Just force the stacked registers to be written in memory. */
+GLOBAL_ENTRY(HYPERVISOR_suspend)
+ alloc r20=ar.pfs,0,0,0,0
+ mov r14=2
+ mov r15=r12
+ ;;
+ /* We don't want to deal with RSE. */
+ flushrs
+ mov r2=__HYPERVISOR_sched_op
+ st4 [r12]=r14
+ ;;
+ break 0x1000
+ ;;
+ mov ar.pfs=r20
+ br.ret.sptk.many b0
+END(HYPERVISOR_suspend)
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/arch/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig Tue Aug 01 16:51:03 2006 -0400
@@ -330,7 +330,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
config ARCH_SPARSEMEM_ENABLE
def_bool y
- depends on (NUMA || EXPERIMENTAL)
+ depends on (NUMA || EXPERIMENTAL) && !X86_64_XEN
config ARCH_MEMORY_PROBE
def_bool y
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Tue Aug 01 16:51:03 2006 -0400
@@ -29,6 +29,11 @@ config XEN_UNPRIVILEGED_GUEST
default !XEN_PRIVILEGED_GUEST
config XEN_PRIVCMD
+ bool
+ depends on PROC_FS
+ default y
+
+config XEN_XENBUS_DEV
bool
depends on PROC_FS
default y
@@ -40,8 +45,59 @@ config XEN_BACKEND
Support for backend device drivers that provide I/O services
to other virtual machines.
+config XEN_BLKDEV_BACKEND
+ tristate "Block-device backend driver"
+ depends on XEN_BACKEND
+ default y
+ help
+ The block-device backend driver allows the kernel to export its
+ block devices to other guests via a high-performance shared-memory
+ interface.
+
+config XEN_BLKDEV_TAP
+ tristate "Block-device tap backend driver"
+ depends on XEN_BACKEND
+ default XEN_PRIVILEGED_GUEST
+ help
+ The block tap driver is an alternative to the block back driver
+ and allows VM block requests to be redirected to userspace through
+ a device interface. The tap allows user-space development of
+ high-performance block backends, where disk images may be implemented
+ as files, in memory, or on other hosts across the network. This
+ driver can safely coexist with the existing blockback driver.
+
+config XEN_NETDEV_BACKEND
+ tristate "Network-device backend driver"
+ depends on XEN_BACKEND && NET
+ default y
+ help
+ The network-device backend driver allows the kernel to export its
+ network devices to other guests via a high-performance shared-memory
+ interface.
+
+config XEN_NETDEV_PIPELINED_TRANSMITTER
+ bool "Pipelined transmitter (DANGEROUS)"
+ depends on XEN_NETDEV_BACKEND
+ default n
+ help
+ If the net backend is a dumb domain, such as a transparent Ethernet
+ bridge with no local IP interface, it is safe to say Y here to get
+ slightly lower network overhead.
+ If the backend has a local IP interface; or may be doing smart things
+ like reassembling packets to perform firewall filtering; or if you
+ are unsure; or if you experience network hangs when this option is
+ enabled; then you must say N here.
+
+config XEN_NETDEV_LOOPBACK
+ tristate "Network-device loopback driver"
+ depends on XEN_NETDEV_BACKEND
+ default y
+ help
+ A two-interface loopback device to emulate a local netfront-netback
+ connection.
+
config XEN_PCIDEV_BACKEND
- tristate "PCI device backend driver"
+ tristate "PCI-device backend driver"
depends on PCI && XEN_BACKEND
default XEN_PRIVILEGED_GUEST
help
@@ -80,50 +136,6 @@ config XEN_PCIDEV_BE_DEBUG
depends on XEN_PCIDEV_BACKEND
default n
-config XEN_BLKDEV_BACKEND
- tristate "Block-device backend driver"
- depends on XEN_BACKEND
- default y
- help
- The block-device backend driver allows the kernel to export its
- block devices to other guests via a high-performance shared-memory
- interface.
-
-config XEN_XENBUS_DEV
- bool
- depends on PROC_FS
- default y
-
-config XEN_NETDEV_BACKEND
- tristate "Network-device backend driver"
- depends on XEN_BACKEND && NET
- default y
- help
- The network-device backend driver allows the kernel to export its
- network devices to other guests via a high-performance shared-memory
- interface.
-
-config XEN_NETDEV_PIPELINED_TRANSMITTER
- bool "Pipelined transmitter (DANGEROUS)"
- depends on XEN_NETDEV_BACKEND
- default n
- help
- If the net backend is a dumb domain, such as a transparent Ethernet
- bridge with no local IP interface, it is safe to say Y here to get
- slightly lower network overhead.
- If the backend has a local IP interface; or may be doing smart things
- like reassembling packets to perform firewall filtering; or if you
- are unsure; or if you experience network hangs when this option is
- enabled; then you must say N here.
-
-config XEN_NETDEV_LOOPBACK
- tristate "Network-device loopback driver"
- depends on XEN_NETDEV_BACKEND
- default y
- help
- A two-interface loopback device to emulate a local netfront-netback
- connection.
-
config XEN_TPMDEV_BACKEND
tristate "TPM-device backend driver"
depends on XEN_BACKEND
@@ -183,7 +195,7 @@ config XEN_SYSFS
depends on SYSFS
default y
help
- Xen hypervisor attributes will show up under /sys/hypervisor/.
+ Xen hypervisor attributes will show up under /sys/hypervisor/.
choice
prompt "Xen version compatibility"
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Tue Aug 01 16:51:03 2006 -0400
@@ -8,6 +8,7 @@ obj-$(CONFIG_XEN_BALLOON) += balloon/
obj-$(CONFIG_XEN_BALLOON) += balloon/
obj-$(CONFIG_XEN_DEVMEM) += char/
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
+obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Tue Aug 01
16:51:03 2006 -0400
@@ -536,18 +536,27 @@ static void xencons_close(struct tty_str
if (DUMMY_TTY(tty))
return;
- if (tty->count == 1) {
- tty->closing = 1;
- tty_wait_until_sent(tty, 0);
- if (DRV(tty->driver)->flush_buffer != NULL)
- DRV(tty->driver)->flush_buffer(tty);
- if (tty->ldisc.flush_buffer != NULL)
- tty->ldisc.flush_buffer(tty);
- tty->closing = 0;
- spin_lock_irqsave(&xencons_lock, flags);
- xencons_tty = NULL;
- spin_unlock_irqrestore(&xencons_lock, flags);
- }
+ down(&tty_sem);
+
+ if (tty->count != 1) {
+ up(&tty_sem);
+ return;
+ }
+
+ /* Prevent other threads from re-opening this tty. */
+ set_bit(TTY_CLOSING, &tty->flags);
+ up(&tty_sem);
+
+ tty->closing = 1;
+ tty_wait_until_sent(tty, 0);
+ if (DRV(tty->driver)->flush_buffer != NULL)
+ DRV(tty->driver)->flush_buffer(tty);
+ if (tty->ldisc.flush_buffer != NULL)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_tty = NULL;
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static struct tty_operations xencons_ops = {
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Tue Aug 01 16:51:03
2006 -0400
@@ -19,14 +19,6 @@
#include <xen/xencons.h>
#include <xen/cpu_hotplug.h>
-#if defined(__i386__) || defined(__x86_64__)
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-#endif
-
extern void ctrl_alt_del(void);
#define SHUTDOWN_INVALID -1
@@ -39,6 +31,14 @@ extern void ctrl_alt_del(void);
*/
#define SHUTDOWN_HALT 4
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
void machine_emergency_restart(void)
{
/* We really want to get pending console data out before we die. */
@@ -60,10 +60,8 @@ void machine_power_off(void)
{
/* We really want to get pending console data out before we die. */
xencons_force_flush();
-#if defined(__i386__) || defined(__x86_64__)
if (pm_power_off)
pm_power_off();
-#endif
HYPERVISOR_shutdown(SHUTDOWN_poweroff);
}
@@ -72,6 +70,7 @@ EXPORT_SYMBOL(machine_halt);
EXPORT_SYMBOL(machine_halt);
EXPORT_SYMBOL(machine_power_off);
+#endif /* defined(__i386__) || defined(__x86_64__) */
/******************************************************************************
* Stop/pickle callback handling.
@@ -81,6 +80,8 @@ static int shutting_down = SHUTDOWN_INVA
static int shutting_down = SHUTDOWN_INVALID;
static void __shutdown_handler(void *unused);
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+
+#if defined(__i386__) || defined(__x86_64__)
/* Ensure we run on the idle task page tables so that we will
switch page tables before running user space. This is needed
@@ -99,56 +100,21 @@ static void switch_idle_mm(void)
mmdrop(mm);
}
-static int __do_suspend(void *ignore)
-{
- int i, j, k, fpp, err;
-
+static void pre_suspend(void)
+{
+ HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+ clear_fixmap(FIX_SHARED_INFO);
+
+ xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+ xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
+}
+
+static void post_suspend(void)
+{
+ int i, j, k, fpp;
extern unsigned long max_pfn;
extern unsigned long *pfn_to_mfn_frame_list_list;
extern unsigned long *pfn_to_mfn_frame_list[];
-
- extern void time_resume(void);
-
- BUG_ON(smp_processor_id() != 0);
- BUG_ON(in_interrupt());
-
- if (xen_feature(XENFEAT_auto_translated_physmap)) {
- printk(KERN_WARNING "Cannot suspend in "
- "auto_translated_physmap mode.\n");
- return -EOPNOTSUPP;
- }
-
- err = smp_suspend();
- if (err)
- return err;
-
- xenbus_suspend();
-
- preempt_disable();
-
-#ifdef __i386__
- kmem_cache_shrink(pgd_cache);
-#endif
- mm_pin_all();
-
- __cli();
- preempt_enable();
-
- gnttab_suspend();
-
- HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
- clear_fixmap(FIX_SHARED_INFO);
-
- xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
- xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
-
- /*
- * We'll stop somewhere inside this hypercall. When it returns,
- * we'll start resuming after the restore.
- */
- HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
-
- shutting_down = SHUTDOWN_INVALID;
set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
@@ -171,6 +137,59 @@ static int __do_suspend(void *ignore)
virt_to_mfn(&phys_to_machine_mapping[i]);
}
HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+}
+
+#else /* !(defined(__i386__) || defined(__x86_64__)) */
+
+#define switch_idle_mm() ((void)0)
+#define mm_pin_all() ((void)0)
+#define pre_suspend() ((void)0)
+#define post_suspend() ((void)0)
+
+#endif
+
+static int __do_suspend(void *ignore)
+{
+ int err;
+
+ extern void time_resume(void);
+
+ BUG_ON(smp_processor_id() != 0);
+ BUG_ON(in_interrupt());
+
+#if defined(__i386__) || defined(__x86_64__)
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ printk(KERN_WARNING "Cannot suspend in "
+ "auto_translated_physmap mode.\n");
+ return -EOPNOTSUPP;
+ }
+#endif
+
+ err = smp_suspend();
+ if (err)
+ return err;
+
+ xenbus_suspend();
+
+ preempt_disable();
+
+ mm_pin_all();
+ local_irq_disable();
+ preempt_enable();
+
+ gnttab_suspend();
+
+ pre_suspend();
+
+ /*
+ * We'll stop somewhere inside this hypercall. When it returns,
+ * we'll start resuming after the restore.
+ */
+ HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+
+ shutting_down = SHUTDOWN_INVALID;
+
+ post_suspend();
gnttab_resume();
@@ -180,7 +199,7 @@ static int __do_suspend(void *ignore)
switch_idle_mm();
- __sti();
+ local_irq_enable();
xencons_resume();
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Aug 01
16:51:03 2006 -0400
@@ -76,6 +76,7 @@ static struct ethtool_ops network_ethtoo
{
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = ethtool_op_set_tx_csum,
+ .get_link = ethtool_op_get_link,
};
netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Tue Aug 01
16:51:03 2006 -0400
@@ -129,6 +129,7 @@ static struct ethtool_ops network_ethtoo
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
+ .get_link = ethtool_op_get_link,
};
/*
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 01
16:51:03 2006 -0400
@@ -99,24 +99,21 @@ static spinlock_t net_schedule_list_lock
#define MAX_MFN_ALLOC 64
static unsigned long mfn_list[MAX_MFN_ALLOC];
static unsigned int alloc_index = 0;
-static DEFINE_SPINLOCK(mfn_lock);
static unsigned long alloc_mfn(void)
{
- unsigned long mfn = 0, flags;
+ unsigned long mfn = 0;
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);
- spin_lock_irqsave(&mfn_lock, flags);
if ( unlikely(alloc_index == 0) )
alloc_index = HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation);
if ( alloc_index != 0 )
mfn = mfn_list[--alloc_index];
- spin_unlock_irqrestore(&mfn_lock, flags);
return mfn;
}
@@ -222,9 +219,13 @@ static void net_rx_action(unsigned long
unsigned long vdata, old_mfn, new_mfn;
struct sk_buff_head rxq;
struct sk_buff *skb;
- u16 notify_list[NET_RX_RING_SIZE];
int notify_nr = 0;
int ret;
+ /*
+ * 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];
skb_queue_head_init(&rxq);
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Aug 01
16:51:03 2006 -0400
@@ -788,6 +788,8 @@ static int network_start_xmit(struct sk_
gso->u.gso.size = skb_shinfo(skb)->gso_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;
@@ -1201,6 +1203,7 @@ static struct ethtool_ops network_ethtoo
.set_sg = xennet_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = xennet_set_tso,
+ .get_link = ethtool_op_get_link,
};
#ifdef CONFIG_SYSFS
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/pciback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Tue Aug 01 16:51:03
2006 -0400
@@ -4,7 +4,8 @@ pciback-y += conf_space.o conf_space_hea
pciback-y += conf_space.o conf_space_header.o \
conf_space_capability.o \
conf_space_capability_vpd.o \
- conf_space_capability_pm.o
+ conf_space_capability_pm.o \
+ conf_space_quirks.o
pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c Tue Aug 01
16:51:03 2006 -0400
@@ -13,9 +13,7 @@
#include <linux/pci.h>
#include "pciback.h"
#include "conf_space.h"
-
-static int permissive = 0;
-module_param(permissive, bool, 0644);
+#include "conf_space_quirks.h"
#define DEFINE_PCI_CONFIG(op,size,type) \
int pciback_##op##_config_##size \
@@ -81,7 +79,7 @@ static int conf_space_write(struct pci_d
case 4:
if (field->u.dw.write)
ret = field->u.dw.write(dev, offset, value,
- entry->data);
+ entry->data);
break;
}
return ret;
@@ -257,40 +255,60 @@ int pciback_config_write(struct pci_dev
* This means that some fields may still be read-only because
* they have entries in the config_field list that intercept
* the write and do nothing. */
- if (permissive) {
+ if (dev_data->permissive) {
switch (size) {
case 1:
err = pci_write_config_byte(dev, offset,
- (u8)value);
+ (u8) value);
break;
case 2:
err = pci_write_config_word(dev, offset,
- (u16)value);
+ (u16) value);
break;
case 4:
err = pci_write_config_dword(dev, offset,
- (u32)value);
+ (u32) value);
break;
}
} else if (!dev_data->warned_on_write) {
dev_data->warned_on_write = 1;
- dev_warn(&dev->dev, "Driver wrote to a read-only "
- "configuration space field!\n");
- dev_warn(&dev->dev, "Write at offset 0x%x size %d\n",
- offset, size);
- dev_warn(&dev->dev, "This may be harmless, but if\n");
- dev_warn(&dev->dev, "you have problems with your "
- "device:\n");
- dev_warn(&dev->dev, "1) see the permissive "
- "attribute in sysfs.\n");
- dev_warn(&dev->dev, "2) report problems to the "
- "xen-devel mailing list along\n");
- dev_warn(&dev->dev, " with details of your device "
- "obtained from lspci.\n");
+ dev_warn(&dev->dev, "Driver tried to write to a "
+ "read-only configuration space field at offset
"
+ "0x%x, size %d. This may be harmless, but if "
+ "you have problems with your device:\n"
+ "1) see permissive attribute in sysfs\n"
+ "2) report problems to the xen-devel "
+ "mailing list along with details of your "
+ "device obtained from lspci.\n", offset, size);
}
}
return pcibios_err_to_errno(err);
+}
+
+void pciback_config_free_dyn_fields(struct pci_dev *dev)
+{
+ struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+ struct config_field_entry *cfg_entry, *t;
+ struct config_field *field;
+
+ dev_dbg(&dev->dev,
+ "free-ing dynamically allocated virtual configuration space
fields\n");
+
+ list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+ field = cfg_entry->field;
+
+ if (field->clean) {
+ field->clean(field);
+
+ if (cfg_entry->data)
+ kfree(cfg_entry->data);
+
+ list_del(&cfg_entry->list);
+ kfree(cfg_entry);
+ }
+
+ }
}
void pciback_config_reset_dev(struct pci_dev *dev)
@@ -337,6 +355,10 @@ int pciback_config_add_field_offset(stru
struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
struct config_field_entry *cfg_entry;
void *tmp;
+
+ /* silently ignore duplicate fields */
+ if (pciback_field_is_dup(dev, field->offset))
+ goto out;
cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
if (!cfg_entry) {
@@ -388,6 +410,10 @@ int pciback_config_init_dev(struct pci_d
goto out;
err = pciback_config_capability_add_fields(dev);
+ if (err)
+ goto out;
+
+ err = pciback_config_quirks_init(dev);
out:
return err;
@@ -395,9 +421,5 @@ int pciback_config_init_dev(struct pci_d
int pciback_config_init(void)
{
- int err;
-
- err = pciback_config_capability_init();
-
- return err;
-}
+ return pciback_config_capability_init();
+}
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h Tue Aug 01
16:51:03 2006 -0400
@@ -33,11 +33,13 @@ typedef int (*conf_byte_read) (struct pc
* values.
*/
struct config_field {
- unsigned int offset;
- unsigned int size;
- conf_field_init init;
+ unsigned int offset;
+ unsigned int size;
+ unsigned int mask;
+ conf_field_init init;
conf_field_reset reset;
- conf_field_free release;
+ conf_field_free release;
+ void (*clean) (struct config_field * field);
union {
struct {
conf_dword_write write;
@@ -52,6 +54,7 @@ struct config_field {
conf_byte_read read;
} b;
} u;
+ struct list_head list;
};
struct config_field_entry {
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Tue Aug 01
16:51:03 2006 -0400
@@ -1,7 +1,8 @@
/*
* PCI Stub Driver - Grabs devices in backend to be exported later
*
- * Author: Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Ryan Wilson <hap9@xxxxxxxxxxxxxx>
+ * Chris Bookholt <hap10@xxxxxxxxxxxxxx>
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -10,6 +11,8 @@
#include <linux/kref.h>
#include <asm/atomic.h>
#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
static char *pci_devs_to_hide = NULL;
module_param_named(hide, pci_devs_to_hide, charp, 0444);
@@ -31,6 +34,7 @@ struct pcistub_device {
struct pci_dev *dev;
struct pciback_device *pdev; /* non-NULL if struct pci_dev is in use
*/
};
+
/* Access to pcistub_devices & seized_devices lists and the initialize_devices
* flag must be locked with pcistub_devices_lock
*/
@@ -76,6 +80,7 @@ static void pcistub_device_release(struc
/* Clean-up the device */
pciback_reset_device(psdev->dev);
+ pciback_config_free_dyn_fields(psdev->dev);
pciback_config_free_dev(psdev->dev);
kfree(pci_get_drvdata(psdev->dev));
pci_set_drvdata(psdev->dev, NULL);
@@ -93,6 +98,32 @@ static inline void pcistub_device_put(st
static inline void pcistub_device_put(struct pcistub_device *psdev)
{
kref_put(&psdev->kref, pcistub_device_release);
+}
+
+static struct pcistub_device *pcistub_device_find(int domain, int bus,
+ int slot, int func)
+{
+ struct pcistub_device *psdev = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (psdev->dev != NULL
+ && domain == pci_domain_nr(psdev->dev->bus)
+ && bus == psdev->dev->bus->number
+ && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+ pcistub_device_get(psdev);
+ goto out;
+ }
+ }
+
+ /* didn't find it */
+ psdev = NULL;
+
+ out:
+ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return psdev;
}
static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
@@ -180,6 +211,7 @@ void pcistub_put_pci_dev(struct pci_dev
* (so it's ready for the next domain)
*/
pciback_reset_device(found_psdev->dev);
+ pciback_config_free_dyn_fields(found_psdev->dev);
pciback_config_reset_dev(found_psdev->dev);
spin_lock_irqsave(&found_psdev->lock, flags);
@@ -392,6 +424,8 @@ static void pcistub_remove(struct pci_de
spin_lock_irqsave(&pcistub_devices_lock, flags);
+ pciback_config_quirk_release(dev);
+
list_for_each_entry(psdev, &pcistub_devices, dev_list) {
if (psdev->dev == dev) {
found_psdev = psdev;
@@ -471,6 +505,19 @@ static inline int str_to_slot(const char
return -EINVAL;
}
+static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
+ *slot, int *func, int *reg, int *size, int *mask)
+{
+ int err;
+
+ err =
+ sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+ func, reg, size, mask);
+ if (err == 7)
+ return 0;
+ return -EINVAL;
+}
+
static int pcistub_device_id_add(int domain, int bus, int slot, int func)
{
struct pcistub_device_id *pci_dev_id;
@@ -523,6 +570,46 @@ static int pcistub_device_id_remove(int
return err;
}
+static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
+ int size, int mask)
+{
+ int err = 0;
+ struct pcistub_device *psdev;
+ struct pci_dev *dev;
+ struct config_field *field;
+
+ psdev = pcistub_device_find(domain, bus, slot, func);
+ if (!psdev || !psdev->dev) {
+ err = -ENODEV;
+ goto out;
+ }
+ dev = psdev->dev;
+
+ /* check for duplicate field */
+ if (pciback_field_is_dup(dev, reg))
+ goto out;
+
+ field = kzalloc(sizeof(*field), GFP_ATOMIC);
+ if (!field) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ field->offset = reg;
+ field->size = size;
+ field->mask = mask;
+ field->init = NULL;
+ field->reset = NULL;
+ field->release = NULL;
+ field->clean = pciback_config_field_free;
+
+ err = pciback_config_quirks_add_field(dev, field);
+ if (err)
+ kfree(field);
+ out:
+ return err;
+}
+
static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
size_t count)
{
@@ -586,6 +673,137 @@ static ssize_t pcistub_slot_show(struct
}
DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ int domain, bus, slot, func, reg, size, mask;
+ int err;
+
+ err = str_to_quirk(buf, &domain, &bus, &slot, &func, ®, &size,
+ &mask);
+ if (err)
+ goto out;
+
+ err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
+
+ out:
+ if (!err)
+ err = count;
+ return err;
+}
+
+static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+{
+ int count = 0;
+ unsigned long flags;
+ extern struct list_head pciback_quirks;
+ struct pciback_config_quirk *quirk;
+ struct pciback_dev_data *dev_data;
+ struct config_field *field;
+ struct config_field_entry *cfg_entry;
+
+ spin_lock_irqsave(&device_ids_lock, flags);
+ list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
+ if (count >= PAGE_SIZE)
+ goto out;
+
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
+ quirk->pdev->bus->number,
+ PCI_SLOT(quirk->pdev->devfn),
+ PCI_FUNC(quirk->pdev->devfn),
+ quirk->devid.vendor, quirk->devid.device,
+ quirk->devid.subvendor,
+ quirk->devid.subdevice);
+
+ dev_data = pci_get_drvdata(quirk->pdev);
+
+ list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+ field = cfg_entry->field;
+ if (count >= PAGE_SIZE)
+ goto out;
+
+ count += scnprintf(buf + count, PAGE_SIZE -
+ count, "\t\t%08x:%01x:%08x\n",
+ field->offset, field->size,
+ field->mask);
+ }
+ }
+
+ out:
+ spin_unlock_irqrestore(&device_ids_lock, flags);
+
+ return count;
+}
+
+DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
+
+static ssize_t permissive_add(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ int domain, bus, slot, func;
+ int err;
+ struct pcistub_device *psdev;
+ struct pciback_dev_data *dev_data;
+ err = str_to_slot(buf, &domain, &bus, &slot, &func);
+ if (err)
+ goto out;
+ psdev = pcistub_device_find(domain, bus, slot, func);
+ if (!psdev) {
+ err = -ENODEV;
+ goto out;
+ }
+ if (!psdev->dev) {
+ err = -ENODEV;
+ goto release;
+ }
+ dev_data = pci_get_drvdata(psdev->dev);
+ /* the driver data for a device should never be null at this point */
+ if (!dev_data) {
+ err = -ENXIO;
+ goto release;
+ }
+ if (!dev_data->permissive) {
+ dev_data->permissive = 1;
+ /* Let user know that what they're doing could be unsafe */
+ dev_warn(&psdev->dev->dev,
+ "enabling permissive mode configuration space
accesses!\n");
+ dev_warn(&psdev->dev->dev,
+ "permissive mode is potentially unsafe!\n");
+ }
+ release:
+ pcistub_device_put(psdev);
+ out:
+ if (!err)
+ err = count;
+ return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+ struct pcistub_device *psdev;
+ struct pciback_dev_data *dev_data;
+ size_t count = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&pcistub_devices_lock, flags);
+ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (count >= PAGE_SIZE)
+ break;
+ if (!psdev->dev)
+ continue;
+ dev_data = pci_get_drvdata(psdev->dev);
+ if (!dev_data || !dev_data->permissive)
+ continue;
+ count +=
+ scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+ pci_name(psdev->dev));
+ }
+ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return count;
+}
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
static int __init pcistub_init(void)
{
@@ -631,6 +849,8 @@ static int __init pcistub_init(void)
driver_create_file(&pciback_pci_driver.driver,
&driver_attr_remove_slot);
driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
+ driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+ driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive);
out:
return err;
@@ -680,6 +900,8 @@ static void __exit pciback_cleanup(void)
driver_remove_file(&pciback_pci_driver.driver,
&driver_attr_remove_slot);
driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
pci_unregister_driver(&pciback_pci_driver);
}
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h Tue Aug 01
16:51:03 2006 -0400
@@ -44,6 +44,7 @@ struct pciback_device {
struct pciback_dev_data {
struct list_head config_fields;
+ int permissive;
int warned_on_write;
};
@@ -61,6 +62,7 @@ void pciback_reset_device(struct pci_dev
/* Access a virtual configuration space for a PCI device */
int pciback_config_init(void);
int pciback_config_init_dev(struct pci_dev *dev);
+void pciback_config_free_dyn_fields(struct pci_dev *dev);
void pciback_config_reset_dev(struct pci_dev *dev);
void pciback_config_free_dev(struct pci_dev *dev);
int pciback_config_read(struct pci_dev *dev, int offset, int size,
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Aug 01
16:51:03 2006 -0400
@@ -852,11 +852,11 @@ static void processing_timeout(unsigned
*/
if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
pak == packet_find_packet(&dataex.current_pak, pak)) {
- list_del(&pak->next);
if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) {
tpm_send_fail_message(pak, pak->req_tag);
}
- packet_free(pak);
+ /* discard future responses */
+ pak->flags |= PACKET_FLAG_DISCARD_RESPONSE;
}
write_unlock_irqrestore(&dataex.pak_lock, flags);
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Tue Aug
01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Tue Aug
01 16:51:03 2006 -0400
@@ -120,7 +120,6 @@ dma_set_mask(struct device *dev, u64 mas
return 0;
}
-#ifdef __i386__
static inline int
dma_get_cache_alignment(void)
{
@@ -128,7 +127,6 @@ dma_get_cache_alignment(void)
* maximum possible, to be safe */
return (1 << INTERNODE_CACHE_SHIFT);
}
-#endif
#define dma_is_consistent(d) (1)
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Aug 01 16:51:03
2006 -0400
@@ -302,23 +302,7 @@ HYPERVISOR_vcpu_op(
return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
}
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- struct sched_shutdown sched_shutdown = {
- .reason = SHUTDOWN_suspend
- };
-
- int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
- &sched_shutdown, srec);
-
- if (rc == -ENOSYS)
- rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
- SHUTDOWN_suspend, srec);
-
- return rc;
-}
+extern int HYPERVISOR_suspend(unsigned long srec);
static inline int
HYPERVISOR_callback_op(
diff -r a75c389e4a7d -r 5ecfc7102cca
linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h Tue Aug 01
16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h Tue Aug 01
16:51:03 2006 -0400
@@ -48,6 +48,8 @@
#define XEN_HYPER_GET_PMD break HYPERPRIVOP_GET_PMD
#define XEN_HYPER_GET_EFLAG break HYPERPRIVOP_GET_EFLAG
#define XEN_HYPER_SET_EFLAG break HYPERPRIVOP_SET_EFLAG
+#define XEN_HYPER_RSM_BE break HYPERPRIVOP_RSM_BE
+#define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR
#define XSI_IFS (XSI_BASE + XSI_IFS_OFS)
#define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS)
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/include/linux/skbuff.h
--- a/linux-2.6-xen-sparse/include/linux/skbuff.h Tue Aug 01 16:42:48
2006 -0400
+++ b/linux-2.6-xen-sparse/include/linux/skbuff.h Tue Aug 01 16:51:03
2006 -0400
@@ -1412,5 +1412,10 @@ static inline void nf_reset(struct sk_bu
static inline void nf_reset(struct sk_buff *skb) {}
#endif /* CONFIG_NETFILTER */
+static inline int skb_is_gso(const struct sk_buff *skb)
+{
+ return skb_shinfo(skb)->gso_size;
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */
diff -r a75c389e4a7d -r 5ecfc7102cca linux-2.6-xen-sparse/net/core/dev.c
--- a/linux-2.6-xen-sparse/net/core/dev.c Tue Aug 01 16:42:48 2006 -0400
+++ b/linux-2.6-xen-sparse/net/core/dev.c Tue Aug 01 16:51:03 2006 -0400
@@ -1089,9 +1089,17 @@ int skb_checksum_help(struct sk_buff *sk
unsigned int csum;
int ret = 0, offset = skb->h.raw - skb->data;
- if (inward) {
- skb->ip_summed = CHECKSUM_NONE;
- goto out;
+ if (inward)
+ goto out_set_summed;
+
+ if (unlikely(skb_shinfo(skb)->gso_size)) {
+ static int warned;
+
+ WARN_ON(!warned);
+ warned = 1;
+
+ /* Let GSO fix up the checksum. */
+ goto out_set_summed;
}
if (skb_cloned(skb)) {
@@ -1108,6 +1116,8 @@ int skb_checksum_help(struct sk_buff *sk
BUG_ON(skb->csum + 2 > offset);
*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+
+out_set_summed:
skb->ip_summed = CHECKSUM_NONE;
out:
return ret;
@@ -1128,17 +1138,35 @@ struct sk_buff *skb_gso_segment(struct s
struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
struct packet_type *ptype;
int type = skb->protocol;
+ int err;
BUG_ON(skb_shinfo(skb)->frag_list);
- BUG_ON(skb->ip_summed != CHECKSUM_HW);
skb->mac.raw = skb->data;
skb->mac_len = skb->nh.raw - skb->data;
__skb_pull(skb, skb->mac_len);
+ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
+ static int warned;
+
+ WARN_ON(!warned);
+ warned = 1;
+
+ if (skb_header_cloned(skb) &&
+ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ return ERR_PTR(err);
+ }
+
rcu_read_lock();
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
+ err = ptype->gso_send_check(skb);
+ segs = ERR_PTR(err);
+ if (err || skb_gso_ok(skb, features))
+ break;
+ __skb_push(skb, skb->data - skb->nh.raw);
+ }
segs = ptype->gso_segment(skb, features);
break;
}
diff -r a75c389e4a7d -r 5ecfc7102cca patches/linux-2.6.16.13/net-csum.patch
--- a/patches/linux-2.6.16.13/net-csum.patch Tue Aug 01 16:42:48 2006 -0400
+++ b/patches/linux-2.6.16.13/net-csum.patch Tue Aug 01 16:51:03 2006 -0400
@@ -1,40 +1,39 @@ diff -pruN ../pristine-linux-2.6.16.13/n
diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c
./net/ipv4/netfilter/ip_nat_proto_tcp.c
--- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c
2006-05-02 22:38:44.000000000 +0100
-+++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-05-04 17:41:37.000000000
+0100
-@@ -129,10 +129,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
++++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-05-16 13:28:19.000000000
+0100
+@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (hdrsize < sizeof(*hdr))
return 1;
- hdr->check = ip_nat_cheat_check(~oldip, newip,
-+ if ((*pskb)->proto_csum_blank) {
++#ifdef CONFIG_XEN
++ if ((*pskb)->proto_csum_blank)
+ hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
-+ } else {
++ else
++#endif
+ hdr->check = ip_nat_cheat_check(~oldip, newip,
ip_nat_cheat_check(oldport ^ 0xFFFF,
newport,
hdr->check));
-+ }
- return 1;
- }
-
diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c
./net/ipv4/netfilter/ip_nat_proto_udp.c
--- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c
2006-05-02 22:38:44.000000000 +0100
-+++ ./net/ipv4/netfilter/ip_nat_proto_udp.c 2006-05-04 17:41:37.000000000
+0100
-@@ -113,11 +113,16 @@ udp_manip_pkt(struct sk_buff **pskb,
++++ ./net/ipv4/netfilter/ip_nat_proto_udp.c 2006-05-16 13:30:14.000000000
+0100
+@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
newport = tuple->dst.u.udp.port;
portptr = &hdr->dest;
}
- if (hdr->check) /* 0 is a special case meaning no checksum */
- hdr->check = ip_nat_cheat_check(~oldip, newip,
+ if (hdr->check) { /* 0 is a special case meaning no checksum */
-+ if ((*pskb)->proto_csum_blank) {
++#ifdef CONFIG_XEN
++ if ((*pskb)->proto_csum_blank)
+ hdr->check = ip_nat_cheat_check(oldip, ~newip,
hdr->check);
-+ } else {
++ else
++#endif
+ hdr->check = ip_nat_cheat_check(~oldip, newip,
ip_nat_cheat_check(*portptr ^ 0xFFFF,
newport,
hdr->check));
-+ }
+ }
*portptr = newport;
return 1;
diff -r a75c389e4a7d -r 5ecfc7102cca
patches/linux-2.6.16.13/xenoprof-generic.patch
--- a/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Aug 01 16:42:48
2006 -0400
+++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Aug 01 16:51:03
2006 -0400
@@ -1,6 +1,6 @@ diff -pru ../pristine-linux-2.6.16.13/dr
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c
./drivers/oprofile/buffer_sync.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/buffer_sync.c 2006-06-27 12:14:53.000000000 +0800
+diff -Naur orig/drivers/oprofile/buffer_sync.c
new/drivers/oprofile/buffer_sync.c
+--- orig/drivers/oprofile/buffer_sync.c 2006-05-02 14:38:44.000000000
-0700
++++ new/drivers/oprofile/buffer_sync.c 2006-07-06 18:19:05.000000000 -0700
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -12,7 +12,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
* This is the core of the buffer management. Each
* CPU buffer is processed and entered into the
* global event buffer. Such processing is necessary
-@@ -275,15 +279,30 @@ static void add_cpu_switch(int i)
+@@ -275,15 +279,31 @@
last_cookie = INVALID_COOKIE;
}
@@ -34,22 +34,23 @@ diff -pru ../pristine-linux-2.6.16.13/dr
+ case CPU_MODE_XEN:
+ add_event_entry(XEN_ENTER_SWITCH_CODE);
+ break;
-+ case CPU_MODE_PASSIVE_START:
-+ add_event_entry(PASSIVE_START_CODE);
-+ break;
-+ case CPU_MODE_PASSIVE_STOP:
-+ add_event_entry(PASSIVE_STOP_CODE);
-+ break;
+ default:
+ break;
+ }
}
-
+
++static void add_domain_switch(unsigned long domain_id)
++{
++ add_event_entry(ESCAPE_CODE);
++ add_event_entry(DOMAIN_SWITCH_CODE);
++ add_event_entry(domain_id);
++}
++
static void
add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
{
-@@ -348,9 +367,9 @@ static int add_us_sample(struct mm_struc
+@@ -348,9 +368,9 @@
* for later lookup from userspace.
*/
static int
@@ -61,7 +62,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
add_sample_entry(s->eip, s->event);
return 1;
} else if (mm) {
-@@ -496,10 +515,11 @@ void sync_buffer(int cpu)
+@@ -496,10 +516,11 @@
struct mm_struct *mm = NULL;
struct task_struct * new;
unsigned long cookie = 0;
@@ -70,34 +71,35 @@ diff -pru ../pristine-linux-2.6.16.13/dr
unsigned int i;
sync_buffer_state state = sb_buffer_start;
unsigned long available;
-+ int domain_switch = NO_DOMAIN_SWITCH;
++ int domain_switch = 0;
down(&buffer_sem);
-@@ -513,12 +533,19 @@ void sync_buffer(int cpu)
+@@ -512,16 +533,18 @@
+ for (i = 0; i < available; ++i) {
struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
- if (is_code(s->eip)) {
+- if (is_code(s->eip)) {
- if (s->event <= CPU_IS_KERNEL) {
-+ if (s->event < CPU_TRACE_BEGIN) {
- /* kernel/userspace switch */
+- /* kernel/userspace switch */
- in_kernel = s->event;
++ if (is_code(s->eip) && !domain_switch) {
++ if (s->event <= CPU_MODE_XEN) {
++ /* xen/kernel/userspace switch */
+ cpu_mode = s->event;
if (state == sb_buffer_start)
state = sb_sample_start;
- add_kernel_ctx_switch(s->event);
-+
-+ if (s->event == CPU_MODE_PASSIVE_START)
-+ domain_switch =
DOMAIN_SWITCH_START_EVENT1;
-+ else if (s->event == CPU_MODE_PASSIVE_STOP)
-+ domain_switch =
DOMAIN_SWITCH_STOP_EVENT1;
-+
-+ if (domain_switch != DOMAIN_SWITCH_START_EVENT2)
-+ add_cpu_mode_switch(s->event);
++ add_cpu_mode_switch(s->event);
} else if (s->event == CPU_TRACE_BEGIN) {
state = sb_bt_start;
add_trace_begin();
-@@ -535,11 +562,20 @@ void sync_buffer(int cpu)
++ } else if (s->event == CPU_DOMAIN_SWITCH) {
++ domain_switch = 1;
+ } else {
+ struct mm_struct * oldmm = mm;
+
+@@ -535,11 +558,16 @@
add_user_ctx_switch(new, cookie);
}
} else {
@@ -106,13 +108,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr
- if (state == sb_bt_start) {
- state = sb_bt_ignore;
-
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
-+ if (domain_switch == DOMAIN_SWITCH_START_EVENT1) {
-+ add_event_entry(s->event);
-+ domain_switch = DOMAIN_SWITCH_START_EVENT2;
-+ } else if (domain_switch == DOMAIN_SWITCH_START_EVENT1)
{
-+ add_sample_entry(s->eip, s->event);
-+ } else if (domain_switch == DOMAIN_SWITCH_STOP_EVENT1) {
-+ domain_switch = NO_DOMAIN_SWITCH;
++ if (domain_switch) {
++ add_domain_switch(s->eip);
++ domain_switch = 0;
+ } else {
+ if (state >= sb_bt_start &&
+ !add_sample(mm, s, cpu_mode)) {
@@ -123,24 +121,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr
}
}
}
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h
./drivers/oprofile/buffer_sync.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/buffer_sync.h 2006-06-27 12:12:09.000000000 +0800
-@@ -9,6 +9,11 @@
-
- #ifndef OPROFILE_BUFFER_SYNC_H
- #define OPROFILE_BUFFER_SYNC_H
-+
-+#define NO_DOMAIN_SWITCH -1
-+#define DOMAIN_SWITCH_START_EVENT1 0
-+#define DOMAIN_SWITCH_START_EVENT2 1
-+#define DOMAIN_SWITCH_STOP_EVENT1 2
-
- /* add the necessary profiling hooks */
- int sync_start(void);
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c
./drivers/oprofile/cpu_buffer.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800
+diff -Naur orig/drivers/oprofile/cpu_buffer.c new/drivers/oprofile/cpu_buffer.c
+--- orig/drivers/oprofile/cpu_buffer.c 2006-05-02 14:38:44.000000000 -0700
++++ new/drivers/oprofile/cpu_buffer.c 2006-07-06 18:19:05.000000000 -0700
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -152,7 +135,16 @@ diff -pru ../pristine-linux-2.6.16.13/dr
* Each CPU has a local buffer that stores PC value/event
* pairs. We also log context switches when we notice them.
* Eventually each CPU's buffer is processed into the global
-@@ -58,7 +62,7 @@ int alloc_cpu_buffers(void)
+@@ -34,6 +38,8 @@
+ #define DEFAULT_TIMER_EXPIRE (HZ / 10)
+ static int work_enabled;
+
++static int32_t current_domain = COORDINATOR_DOMAIN;
++
+ void free_cpu_buffers(void)
+ {
+ int i;
+@@ -58,7 +64,7 @@
goto fail;
b->last_task = NULL;
@@ -161,7 +153,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
b->tracing = 0;
b->buffer_size = buffer_size;
b->tail_pos = 0;
-@@ -114,7 +118,7 @@ void cpu_buffer_reset(struct oprofile_cp
+@@ -114,7 +120,7 @@
* collected will populate the buffer with proper
* values to initialize the buffer
*/
@@ -170,7 +162,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
cpu_buf->last_task = NULL;
}
-@@ -164,13 +168,13 @@ add_code(struct oprofile_cpu_buffer * bu
+@@ -164,13 +170,13 @@
* because of the head/tail separation of the writer and reader
* of the CPU buffer.
*
@@ -188,7 +180,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
{
struct task_struct * task;
-@@ -181,16 +185,14 @@ static int log_sample(struct oprofile_cp
+@@ -181,18 +187,18 @@
return 0;
}
@@ -207,12 +199,43 @@ diff -pru ../pristine-linux-2.6.16.13/dr
-
+
/* notice a task switch */
- if (cpu_buf->last_task != task) {
+- if (cpu_buf->last_task != task) {
++ /* if not processing other domain samples */
++ if ((cpu_buf->last_task != task) &&
++ (current_domain == COORDINATOR_DOMAIN)) {
cpu_buf->last_task = task;
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h
./drivers/oprofile/cpu_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/cpu_buffer.h 2006-06-27 10:38:08.000000000 +0800
-@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
+ add_code(cpu_buf, (unsigned long)task);
+ }
+@@ -269,6 +275,25 @@
+ add_sample(cpu_buf, pc, 0);
+ }
+
++int oprofile_add_domain_switch(int32_t domain_id)
++{
++ struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++
++ /* should have space for switching into and out of domain
++ (2 slots each) plus one sample and one cpu mode switch */
++ if (((nr_available_slots(cpu_buf) < 6) &&
++ (domain_id != COORDINATOR_DOMAIN)) ||
++ (nr_available_slots(cpu_buf) < 2))
++ return 0;
++
++ add_code(cpu_buf, CPU_DOMAIN_SWITCH);
++ add_sample(cpu_buf, domain_id, 0);
++
++ current_domain = domain_id;
++
++ return 1;
++}
++
+ /*
+ * This serves to avoid cpu buffer overflow, and makes sure
+ * the task mortuary progresses
+diff -Naur orig/drivers/oprofile/cpu_buffer.h new/drivers/oprofile/cpu_buffer.h
+--- orig/drivers/oprofile/cpu_buffer.h 2006-05-02 14:38:44.000000000 -0700
++++ new/drivers/oprofile/cpu_buffer.h 2006-07-06 18:19:05.000000000 -0700
+@@ -36,7 +36,7 @@
volatile unsigned long tail_pos;
unsigned long buffer_size;
struct task_struct * last_task;
@@ -221,7 +244,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
int tracing;
struct op_sample * buffer;
unsigned long sample_received;
-@@ -51,7 +51,13 @@ extern struct oprofile_cpu_buffer cpu_bu
+@@ -51,7 +51,10 @@
void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
/* transient events for the CPU buffer -> event buffer */
@@ -230,17 +253,14 @@ diff -pru ../pristine-linux-2.6.16.13/dr
+#define CPU_MODE_USER 0
+#define CPU_MODE_KERNEL 1
+#define CPU_MODE_XEN 2
-+#define CPU_MODE_PASSIVE_START 3
-+#define CPU_MODE_PASSIVE_STOP 4
-+#define CPU_TRACE_BEGIN 5
-+
-+#define IGNORED_PC 0
++#define CPU_TRACE_BEGIN 3
++#define CPU_DOMAIN_SWITCH 4
#endif /* OPROFILE_CPU_BUFFER_H */
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
./drivers/oprofile/event_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
2006-05-03 05:38:44.000000000 +0800
-+++ ./drivers/oprofile/event_buffer.h 2006-06-19 22:43:53.000000000 +0800
-@@ -29,11 +29,14 @@ void wake_up_buffer_waiter(void);
+diff -Naur orig/drivers/oprofile/event_buffer.h
new/drivers/oprofile/event_buffer.h
+--- orig/drivers/oprofile/event_buffer.h 2006-05-02 14:38:44.000000000
-0700
++++ new/drivers/oprofile/event_buffer.h 2006-07-06 18:19:05.000000000
-0700
+@@ -29,15 +29,20 @@
#define CPU_SWITCH_CODE 2
#define COOKIE_SWITCH_CODE 3
#define KERNEL_ENTER_SWITCH_CODE 4
@@ -251,14 +271,20 @@ diff -pru ../pristine-linux-2.6.16.13/dr
#define TRACE_BEGIN_CODE 8
#define TRACE_END_CODE 9
+#define XEN_ENTER_SWITCH_CODE 10
-+#define PASSIVE_START_CODE 11
-+#define PASSIVE_STOP_CODE 12
++#define DOMAIN_SWITCH_CODE 11
#define INVALID_COOKIE ~0UL
#define NO_COOKIE 0UL
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c
./drivers/oprofile/oprof.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/oprof.c 2006-06-19 23:45:17.000000000 +0800
+
++/* Constant used to refer to coordinator domain (Xen) */
++#define COORDINATOR_DOMAIN -1
++
+ /* add data to the event buffer */
+ void add_event_entry(unsigned long data);
+
+diff -Naur orig/drivers/oprofile/oprof.c new/drivers/oprofile/oprof.c
+--- orig/drivers/oprofile/oprof.c 2006-05-02 14:38:44.000000000 -0700
++++ new/drivers/oprofile/oprof.c 2006-07-06 18:19:05.000000000 -0700
@@ -5,6 +5,10 @@
* @remark Read the file COPYING
*
@@ -279,7 +305,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
struct oprofile_operations oprofile_ops;
unsigned long oprofile_started;
-@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem);
+@@ -33,6 +37,32 @@
*/
static int timer = 0;
@@ -312,10 +338,10 @@ diff -pru ../pristine-linux-2.6.16.13/dr
int oprofile_setup(void)
{
int err;
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h
./drivers/oprofile/oprof.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-03
05:38:44.000000000 +0800
-+++ ./drivers/oprofile/oprof.h 2006-06-19 23:42:36.000000000 +0800
-@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_
+diff -Naur orig/drivers/oprofile/oprof.h new/drivers/oprofile/oprof.h
+--- orig/drivers/oprofile/oprof.h 2006-05-02 14:38:44.000000000 -0700
++++ new/drivers/oprofile/oprof.h 2006-07-06 18:19:05.000000000 -0700
+@@ -35,5 +35,8 @@
void oprofile_timer_init(struct oprofile_operations * ops);
int oprofile_set_backtrace(unsigned long depth);
@@ -324,9 +350,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr
+int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
#endif /* OPROF_H */
-diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
./drivers/oprofile/oprofile_files.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
2006-05-03 05:38:44.000000000 +0800
-+++ ./drivers/oprofile/oprofile_files.c 2006-06-19 23:29:07.000000000
+0800
+diff -Naur orig/drivers/oprofile/oprofile_files.c
new/drivers/oprofile/oprofile_files.c
+--- orig/drivers/oprofile/oprofile_files.c 2006-05-02 14:38:44.000000000
-0700
++++ new/drivers/oprofile/oprofile_files.c 2006-07-06 18:19:05.000000000
-0700
@@ -5,15 +5,21 @@
* @remark Read the file COPYING
*
@@ -350,7 +376,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
unsigned long fs_buffer_size = 131072;
unsigned long fs_cpu_buffer_size = 8192;
unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
-@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file *
+@@ -117,11 +123,202 @@
static struct file_operations dump_fops = {
.write = dump_write,
};
@@ -554,8 +580,9 @@ diff -pru ../pristine-linux-2.6.16.13/dr
oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
oprofilefs_create_ulong(sb, root, "buffer_watershed",
&fs_buffer_watershed);
---- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-03
05:38:44.000000000 +0800
-+++ ./include/linux/oprofile.h 2006-06-19 23:52:00.000000000 +0800
+diff -Naur orig/include/linux/oprofile.h new/include/linux/oprofile.h
+--- orig/include/linux/oprofile.h 2006-05-02 14:38:44.000000000 -0700
++++ new/include/linux/oprofile.h 2006-07-06 18:19:31.000000000 -0700
@@ -16,6 +16,8 @@
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -565,7 +592,7 @@ diff -pru ../pristine-linux-2.6.16.13/dr
struct super_block;
struct dentry;
-@@ -27,6 +29,11 @@ struct oprofile_operations {
+@@ -27,6 +29,11 @@
/* create any necessary configuration files in the oprofile fs.
* Optional. */
int (*create_files)(struct super_block * sb, struct dentry * root);
@@ -577,3 +604,12 @@ diff -pru ../pristine-linux-2.6.16.13/dr
/* Do any necessary interrupt setup. Optional. */
int (*setup)(void);
/* Do any necessary interrupt shutdown. Optional. */
+@@ -68,6 +75,8 @@
+ /* add a backtrace entry, to be called from the ->backtrace callback */
+ void oprofile_add_trace(unsigned long eip);
+
++/* add a domain switch entry */
++int oprofile_add_domain_switch(int32_t domain_id);
+
+ /**
+ * Create a file of the given name as a child of the given root, with
diff -r a75c389e4a7d -r 5ecfc7102cca tools/Makefile
--- a/tools/Makefile Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/Makefile Tue Aug 01 16:51:03 2006 -0400
@@ -7,7 +7,7 @@ SUBDIRS-y += misc
SUBDIRS-y += misc
SUBDIRS-y += examples
SUBDIRS-y += xentrace
-SUBDIRS-$(CONFIG_X86) += xcutils
+SUBDIRS-$(CONFIG_XCUTILS) += xcutils
SUBDIRS-y += firmware
SUBDIRS-y += security
SUBDIRS-y += console
@@ -16,6 +16,8 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
SUBDIRS-$(VTPM_TOOLS) += vtpm
SUBDIRS-y += xenstat
+SUBDIRS-y += libaio
+SUBDIRS-y += blktap
# These don't cross-compile
ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
@@ -58,10 +60,13 @@ check_clean:
.PHONY: ioemu ioemuinstall ioemuclean
ifdef CONFIG_IOEMU
-ioemu ioemuinstall ioemuclean:
- [ -f ioemu/config-host.h ] || \
- (cd ioemu; sh ./configure --prefix=usr)
- $(MAKE) -C ioemu $(patsubst ioemu%,%,$@)
+export IOEMU_DIR ?= ioemu
+ioemu ioemuinstall:
+ [ -f $(IOEMU_DIR)/config-host.mak ] || \
+ (cd $(IOEMU_DIR) && sh configure --prefix=/usr)
+ $(MAKE) -C $(IOEMU_DIR) $(patsubst ioemu%,%,$@)
+ioemuclean:
+ $(MAKE) -C $(IOEMU_DIR) distclean
else
ioemu ioemuinstall ioemuclean:
endif
diff -r a75c389e4a7d -r 5ecfc7102cca tools/domctrl/DomU.dts.in
--- a/tools/domctrl/DomU.dts.in Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/domctrl/DomU.dts.in Tue Aug 01 16:51:03 2006 -0400
@@ -66,7 +66,7 @@
linux,platform = <501>;
linux,initrd-start = <@INITRD_START@>;
linux,initrd-end = <@INITRD_END@>;
- linux,stdout-package = "&/xen/console";
+ linux,stdout-package = <&/xen/console>;
linux,stdout-path = "/xen/console";
interrupt-controller = <&/xen>;
cpu = <&/cpus/@CPU_TYPE@@0>;
diff -r a75c389e4a7d -r 5ecfc7102cca tools/domctrl/DomU.sh
--- a/tools/domctrl/DomU.sh Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/domctrl/DomU.sh Tue Aug 01 16:51:03 2006 -0400
@@ -19,7 +19,7 @@ s%@DOMAIN_NAME@%$DOMAIN_NAME%g;
s%@DOMAIN_NAME@%$DOMAIN_NAME%g;
s%@DOMAIN_ID@%$DOMAIN_ID%g;
s%@MODEL@%$MODEL%g;
-s%@COMAPTIBLE@%$COMPATIBLE%g;
+s%@COMPATIBLE@%$COMPATIBLE%g;
s%@BOOTARGS@%$BOOTARGS%g;
s%@INITRD_START@%$INITRD_START%g;
s%@INITRD_END@%$INITRD_END%g;
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/Makefile
--- a/tools/examples/Makefile Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/Makefile Tue Aug 01 16:51:03 2006 -0400
@@ -18,6 +18,8 @@ XEN_CONFIGS += xmexample2
XEN_CONFIGS += xmexample2
XEN_CONFIGS += xmexample.hvm
XEN_CONFIGS += xmexample.vti
+XEN_CONFIGS += xend-pci-quirks.sxp
+XEN_CONFIGS += xend-pci-permissive.sxp
# Xen script dir and scripts to go there.
XEN_SCRIPT_DIR = /etc/xen/scripts
@@ -26,7 +28,8 @@ XEN_SCRIPTS += network-nat vif-nat
XEN_SCRIPTS += network-nat vif-nat
XEN_SCRIPTS += block
XEN_SCRIPTS += block-enbd block-nbd
-XEN_SCRIPTS += vtpm vtpm-delete vtpm-addtodb
+XEN_SCRIPTS += blktap
+XEN_SCRIPTS += vtpm vtpm-delete
XEN_SCRIPTS += xen-hotplug-cleanup
XEN_SCRIPTS += external-device-migrate
XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/README
--- a/tools/examples/README Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/README Tue Aug 01 16:51:03 2006 -0400
@@ -25,7 +25,6 @@ vif-nat - xen virtual networ
vif-nat - xen virtual network start/stop script in NAT mode
vif-route - xen virtual network start/stop script in routed mode
vtpm - called by xen-backend.agent to bind/unbind vTPM devices
-vtpm-addtodb - script for adding a vTPM instance to the vTPM table
vtpm-common.sh - common code for vTPM handling
vtpm-delete - remove an entry from the vTPM table given the
domain's name
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/vtpm-common.sh
--- a/tools/examples/vtpm-common.sh Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/vtpm-common.sh Tue Aug 01 16:51:03 2006 -0400
@@ -24,12 +24,9 @@ VTPMDB="/etc/xen/vtpm.db"
#In the vtpm-impl file some commands should be defined:
# vtpm_create, vtpm_setup, vtpm_start, etc. (see below)
-#This should be indicated by setting VTPM_IMPL_DEFINED.
if [ -r "$dir/vtpm-impl" ]; then
. "$dir/vtpm-impl"
-fi
-
-if [ -z "$VTPM_IMPL_DEFINED" ]; then
+else
function vtpm_create () {
true
}
@@ -245,6 +242,12 @@ function vtpm_create_instance () {
claim_lock vtpmdb
instance=$(vtpmdb_find_instance $domname)
+
+ if [ "$instance" == "0" -a "$reason" != "create" ]; then
+ release_lock vtpmdb
+ return
+ fi
+
if [ "$instance" == "0" ]; then
#Try to give the preferred instance to the domain
instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
@@ -317,7 +320,7 @@ function vtpm_delete_instance () {
# "-1" : the given machine name is invalid
# "0" : this is not an address of this machine
# "1" : this is an address local to this machine
-function isLocalAddress() {
+function vtpm_isLocalAddress() {
local addr res
addr=$(ping $1 -c 1 | \
gawk '{ print substr($3,2,length($3)-2); exit }')
@@ -347,7 +350,7 @@ function isLocalAddress() {
# 2nd: name of the domain to migrate
# 3rd: the migration step to perform
function vtpm_migration_step() {
- local res=$(isLocalAddress $1)
+ local res=$(vtpm_isLocalAddress $1)
if [ "$res" == "0" ]; then
vtpm_migrate $1 $2 $3
fi
@@ -361,8 +364,39 @@ function vtpm_migration_step() {
# 3rd: the last successful migration step that was done
function vtpm_recover() {
local res
- res=$(isLocalAddress $1)
+ res=$(vtpm_isLocalAddress $1)
if [ "$res" == "0" ]; then
vtpm_migrate_recover $1 $2 $3
fi
}
+
+
+#Determine the domain id given a domain's name.
+#1st parameter: name of the domain
+#return value: domain id or -1 if domain id could not be determined
+function vtpm_domid_from_name () {
+ local id name ids
+ ids=$(xenstore-list /local/domain)
+ for id in $ids; do
+ name=$(xenstore-read /local/domain/$id/name)
+ if [ "$name" == "$1" ]; then
+ echo "$id"
+ return
+ fi
+ done
+ echo "-1"
+}
+
+
+#Add a virtual TPM instance number and its associated domain name
+#to the VTPMDB file and activate usage of this virtual TPM instance
+#by writing the instance number into the xenstore
+#1st parm: name of virtual machine
+#2nd parm: instance of assoicate virtual TPM
+function vtpm_add_and_activate() {
+ local domid=$(vtpm_domid_from_name $1)
+ if [ "$domid" != "-1" ]; then
+ vtpmdb_add_instance $1 $2
+ xenstore-write backend/vtpm/$domid/0/instance $2
+ fi
+}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/vtpm-impl
--- a/tools/examples/vtpm-impl Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/vtpm-impl Tue Aug 01 16:51:03 2006 -0400
@@ -32,8 +32,6 @@
# OF THE POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
-VTPM_IMPL_DEFINED=1
-
# | SRC | TAG | CMD SIZE | ORD
| type| mode
TPM_CMD_OPEN=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x01
TPM_CMD_RESM=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x02
@@ -44,6 +42,8 @@ TPM_SUCCESS=00000000
TX_VTPM_MANAGER=/var/vtpm/fifos/from_console.fifo
RX_VTPM_MANAGER=/var/vtpm/fifos/to_console.fifo
+
+VTPM_MIG=/usr/bin/vtpm_migrator
# -------------------- Helpers for binary streams -----------
@@ -67,11 +67,17 @@ function vtpm_manager_cmd() {
local inst=$2;
local inst_bin=$(hex32_to_bin $inst);
+ claim_lock vtpm_mgr
+
#send cmd to vtpm_manager
printf "$cmd$inst_bin" > $TX_VTPM_MANAGER
#recv response
+ set +e
local resp_hex=`dd skip=10 bs=1 count=4 if=$RX_VTPM_MANAGER 2> /dev/null |
xxd -ps`
+ set -e
+
+ release_lock vtpm_mgr
#return whether the command was successful
if [ $resp_hex != $TPM_SUCCESS ]; then
@@ -126,11 +132,55 @@ function vtpm_delete() {
fi
}
+# Perform a migration step. This function differentiates between migration
+# to the local host or to a remote machine.
+# Parameters:
+# 1st: destination host to migrate to
+# 2nd: name of the domain to migrate
+# 3rd: the migration step to perform
function vtpm_migrate() {
- echo "Error: vTPM migration accross machines not implemented."
+ local instance res
+
+ instance=$(vtpmdb_find_instance $2)
+ if [ "$instance" == "" ]; then
+ log err "VTPM Migratoin failed. Unable to translation of domain name"
+ echo "Error: VTPM Migration failed while looking up instance number"
+ fi
+
+ case "$3" in
+ 0)
+ #Incicate migration supported
+ echo "0"
+ ;;
+
+ 1)
+ # Get Public Key from Destination
+ # Call vtpm_manager's migration part 1
+ claim_lock vtpm_mgr
+ $VTPM_MIG $1 $2 $instance $3
+ release_lock vtpm_mgr
+ ;;
+
+ 2)
+ # Call manager's migration step 2 and send result to destination
+ # If successful remove from db
+ claim_lock vtpm_mgr
+ $VTPM_MIG $1 $2 $instance $3
+ release_lock vtpm_mgr
+ ;;
+
+ 3)
+ if `ps x | grep "$VTPM_MIG $1"`; then
+ log err "VTPM Migration failed to complete."
+ echo "Error: VTPM Migration failed to complete."
+ fi
+ ;;
+ esac
+
}
+
function vtpm_migrate_recover() {
- true
+ echo "Error: Recovery not supported yet"
}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/xen-backend.agent
--- a/tools/examples/xen-backend.agent Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xen-backend.agent Tue Aug 01 16:51:03 2006 -0400
@@ -7,6 +7,9 @@ claim_lock xenbus_hotplug_global
claim_lock xenbus_hotplug_global
case "$XENBUS_TYPE" in
+ tap)
+ /etc/xen/scripts/blktap "$ACTION"
+ ;;
vbd)
/etc/xen/scripts/block "$ACTION"
;;
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/xen-backend.rules
--- a/tools/examples/xen-backend.rules Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xen-backend.rules Tue Aug 01 16:51:03 2006 -0400
@@ -1,3 +1,4 @@ SUBSYSTEM=="xen-backend", KERNEL=="vbd*"
+SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap
$env{ACTION}"
SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block
$env{ACTION}"
SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm
$env{ACTION}"
SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script}
online"
diff -r a75c389e4a7d -r 5ecfc7102cca tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/examples/xmexample.hvm Tue Aug 01 16:51:03 2006 -0400
@@ -54,7 +54,7 @@ name = "ExampleHVMDomain"
# Optionally define mac and/or bridge for the network interfaces.
# Random MACs are assigned if not given.
-#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ]
+#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ]
# type=ioemu specify the NIC is an ioemu device not netfront
vif = [ 'type=ioemu, bridge=xenbr0' ]
@@ -130,8 +130,13 @@ vnc=1
vnc=1
#----------------------------------------------------------------------------
-# enable spawning vncviewer(only valid when vnc=1), default = 1
-vncviewer=1
+# set VNC display number, default = domid
+#vncdisplay=1
+
+#----------------------------------------------------------------------------
+# enable spawning vncviewer for domain's console
+# (only valid when vnc=1), default = 0
+#vncconsole=0
#----------------------------------------------------------------------------
# no graphics, use serial port
@@ -146,10 +151,6 @@ stdvga=0
# then xm console or minicom can connect
serial='pty'
-#----------------------------------------------------------------------------
-# enable ne2000, default = 0(use pcnet)
-ne2000=0
-
#-----------------------------------------------------------------------------
# enable audio support
diff -r a75c389e4a7d -r 5ecfc7102cca tools/firmware/vmxassist/vmxassist.ld
--- a/tools/firmware/vmxassist/vmxassist.ld Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/firmware/vmxassist/vmxassist.ld Tue Aug 01 16:51:03 2006 -0400
@@ -11,8 +11,7 @@ SECTIONS
_btext = .;
*(.text)
*(.rodata)
- *(.rodata.str1.1)
- *(.rodata.str1.4)
+ *(.rodata.*)
_etext = .;
}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/Changelog
--- a/tools/ioemu/Changelog Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/Changelog Tue Aug 01 16:51:03 2006 -0400
@@ -1,3 +1,84 @@ version 0.6.1:
+version 0.8.1:
+
+ - USB tablet support (Brad Campbell, Anthony Liguori)
+ - win32 host serial support (Kazu)
+ - PC speaker support (Joachim Henke)
+ - IDE LBA48 support (Jens Axboe)
+ - SSE3 support
+ - Solaris port (Ben Taylor)
+ - Preliminary SH4 target (Samuel Tardieu)
+ - VNC server (Anthony Liguori)
+ - slirp fixes (Ed Swierk et al.)
+ - USB fixes
+ - ARM Versatile Platform Baseboard emulation (Paul Brook)
+
+version 0.8.0:
+
+ - ARM system emulation: Arm Integrator/CP board with an arm1026ej-s
+ cpu (Paul Brook)
+ - SMP support
+ - Mac OS X cocoa improvements (Mike Kronenberg)
+ - Mac OS X CoreAudio driver (Mike Kronenberg)
+ - DirectSound driver (malc)
+ - ALSA audio driver (malc)
+ - new audio options: '-soundhw' and '-audio-help' (malc)
+ - ES1370 PCI audio device (malc)
+ - Initial USB support
+ - Linux host serial port access
+ - Linux host low level parallel port access
+ - New network emulation code supporting VLANs.
+ - MIPS and MIPSel User Linux emulation
+ - MIPS fixes to boot Linux (Daniel Jacobowitz)
+ - NX bit support
+ - Initial SPARC SMP support (Blue Swirl)
+ - Major overhaul of the virtual FAT driver for read/write support
+ (Johannes Schindelin)
+
+version 0.7.2:
+
+ - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
+ - merge self modifying code handling in dirty ram page mecanism.
+ - MIPS fixes (Ralf Baechle)
+ - better user net performances
+
+version 0.7.1:
+
+ - read-only Virtual FAT support (Johannes Schindelin)
+ - Windows 2000 install disk full hack (original idea from Vladimir
+ N. Oleynik)
+ - VMDK disk image creation (Filip Navara)
+ - SPARC64 progress (Blue Swirl)
+ - initial MIPS support (Jocelyn mayer)
+ - MIPS improvements (Ralf Baechle)
+ - 64 bit fixes in user networking (initial patch by Gwenole Beauchesne)
+ - IOAPIC support (Filip Navara)
+
+version 0.7.0:
+
+ - better BIOS translation and HDD geometry auto-detection
+ - user mode networking bug fix
+ - undocumented FPU ops support
+ - Cirrus VGA: support for 1280x1024x[8,15,16] modes
+ - 'pidfile' option
+ - .dmg disk image format support (Johannes Schindelin)
+ - keymaps support (initial patch by Johannes Schindelin)
+ - big endian ARM support (Lennert Buytenhek)
+ - added generic 64 bit target support
+ - x86_64 target support
+ - initial APIC support
+ - MMX/SSE/SSE2/PNI support
+ - PC parallel port support (Mark Jonckheere)
+ - initial SPARC64 support (Blue Swirl)
+ - SPARC target boots Linux (Blue Swirl)
+ - armv5te user mode support (Paul Brook)
+ - ARM VFP support (Paul Brook)
+ - ARM "Angel" semihosting syscalls (Paul Brook)
+ - user mode gdb stub support (Paul Brook)
+ - Samba 3 support
+ - initial Cocoa support (Pierre d'Herbemont)
+ - generic FPU emulation code
+ - Virtual PC read-only disk image support (Alex Beregszaszi)
+
version 0.6.1:
- Mac OS X port (Pierre d'Herbemont)
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/Makefile
--- a/tools/ioemu/Makefile Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/Makefile Tue Aug 01 16:51:03 2006 -0400
@@ -3,89 +3,112 @@ include $(XEN_ROOT)/tools/Rules.mk
-include config-host.mak
-CFLAGS+=-g -fno-strict-aliasing
+CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
-endif
-ifdef CONFIG_WIN32
-CFLAGS+=-fpack-struct
endif
LDFLAGS=-g
LIBS=
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-TOOLS=qemu-img
+TOOLS=qemu-img$(EXESUF)
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
-#DOCS=qemu-doc.html qemu-tech.html qemu.1
+ifdef BUILD_DOCS
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
+else
+DOCS=
+endif
-.PHONY: all
-all: $(DOCS) HEADERS
+all: $(DOCS)
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
-qemu-img: qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c
block-cloop.c
+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)
dyngen$(EXESUF): dyngen.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
-.PHONY: clean
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h
opc-arm.h gen-op-arm.h
- rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~
- #$(MAKE) -C tests clean
+ rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
+ $(MAKE) -C tests clean
for d in $(TARGET_DIRS); do \
- $(MAKE) -C $$d $@ || exit 1 ; \
+ [ -d $$d ] && $(MAKE) -C $$d $@ || exit 0 ; \
done
- rm -f config-host.mak config-host.h
- rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h
-.PHONY: distclean
distclean: clean
- rm -f config-host.mak config-host.h
- rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h
+ rm -f config-host.mak config-host.h $(DOCS)
for d in $(TARGET_DIRS); do \
- $(MAKE) -C $$d $@ || exit 1 ; \
+ rm -rf $$d || exit 1 ; \
done
KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \
ar de en-us fi fr-be hr it lv nl pl ru th \
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
-.PHONY: install
-install: all
- mkdir -p "$(bindir)"
- mkdir -p "$(DESTDIR)/$(datadir)"
- mkdir -p "$(DESTDIR)/$(datadir)/keymaps"
- install -m 644 $(addprefix keymaps/,$(KEYMAPS))
"$(DESTDIR)/$(datadir)/keymaps"
+install-doc: $(DOCS)
+ mkdir -p "$(DESTDIR)$(docdir)"
+ $(INSTALL) -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)"
+ifndef CONFIG_WIN32
+ mkdir -p "$(DESTDIR)$(mandir)/man1"
+ $(INSTALL) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
+endif
+
+install: all $(if $(BUILD_DOCS),install-doc)
+ mkdir -p "$(DESTDIR)$(bindir)"
+# $(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 \
+# $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x
"$(DESTDIR)$(datadir)"; \
+# done
+ifndef CONFIG_WIN32
+ mkdir -p "$(DESTDIR)$(datadir)/keymaps"
+ for x in $(KEYMAPS); do \
+ $(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x
"$(DESTDIR)$(datadir)/keymaps"; \
+ done
+endif
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
# various test targets
-.PHONY: test speed test2
test speed test2: all
$(MAKE) -C tests $@
-.PHONY: TAGS
TAGS:
etags *.[ch] tests/*.[ch]
+
+cscope:
+ rm -f ./cscope.*
+ find . -name "*.[ch]" -print > ./cscope.files
+ cscope -b
# documentation
%.html: %.texi
texi2html -monolithic -number $<
+%.info: %.texi
+ makeinfo $< -o $@
+
+%.dvi: %.texi
+ texi2dvi $<
+
qemu.1: qemu-doc.texi
- ./texi2pod.pl $< qemu.pod
+ perl -w $(SRC_PATH)/texi2pod.pl $< qemu.pod
pod2man --section=1 --center=" " --release=" " qemu.pod > $@
+
+qemu-img.1: qemu-img.texi
+ perl -w $(SRC_PATH)/texi2pod.pl $< qemu-img.pod
+ pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
FILE=qemu-$(shell cat VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
-.PHONY: tar
tar:
rm -rf /tmp/$(FILE)
cp -r . /tmp/$(FILE)
@@ -93,36 +116,34 @@ tar:
rm -rf /tmp/$(FILE)
# generate a binary distribution
-.PHONY: tarbin
tarbin:
- ( cd $(DESTDIR) ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
- $(DESTDIR)/$(bindir)/qemu $(DESTDIR)/$(bindir)/qemu-fast \
- $(DESTDIR)/$(bindir)/qemu-system-ppc \
- $(DESTDIR)/$(bindir)/qemu-i386 \
- $(DESTDIR)/$(bindir)/qemu-arm \
- $(DESTDIR)/$(bindir)/qemu-sparc \
- $(DESTDIR)/$(bindir)/qemu-ppc \
- $(DESTDIR)/$(mandir)/man1/qemu.1 $(DESTDIR)/$(mandir)/man1/qemu-mkcow.1
)
+ ( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
+ $(bindir)/qemu \
+ $(bindir)/qemu-system-ppc \
+ $(bindir)/qemu-system-sparc \
+ $(bindir)/qemu-system-x86_64 \
+ $(bindir)/qemu-system-mips \
+ $(bindir)/qemu-system-mipsel \
+ $(bindir)/qemu-system-arm \
+ $(bindir)/qemu-i386 \
+ $(bindir)/qemu-arm \
+ $(bindir)/qemu-armeb \
+ $(bindir)/qemu-sparc \
+ $(bindir)/qemu-ppc \
+ $(bindir)/qemu-mips \
+ $(bindir)/qemu-mipsel \
+ $(bindir)/qemu-img \
+ $(datadir)/bios.bin \
+ $(datadir)/vgabios.bin \
+ $(datadir)/vgabios-cirrus.bin \
+ $(datadir)/ppc_rom.bin \
+ $(datadir)/video.x \
+ $(datadir)/proll.elf \
+ $(datadir)/linux_boot.bin \
+ $(docdir)/qemu-doc.html \
+ $(docdir)/qemu-tech.html \
+ $(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
ifneq ($(wildcard .depend),)
include .depend
endif
-
-.PHONY: HEADERS
-HEADERS:
-
-ifdef CONFIG_SDL
-HEADERS: keysym_adapter_sdl.h
-endif
-
-ifdef CONFIG_VNC
-HEADERS: keysym_adapter_vnc.h
-endif
-
-keysym_adapter_sdl.h: Makefile create_keysym_header.sh
- sh create_keysym_header.sh sdl "$(SDL_CFLAGS)"
-
-keysym_adapter_vnc.h: Makefile create_keysym_header.sh
- sh create_keysym_header.sh vnc "$(VNC_CFLAGS)"
-
-
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/README
--- a/tools/ioemu/README Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/README Tue Aug 01 16:51:03 2006 -0400
@@ -1,61 +1,3 @@ The QEMU x86 emulator
-The QEMU x86 emulator
----------------------
-
-INSTALLATION
-------------
-
-Type
-
- ./configure
- make
-
-to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
-supported target CPUs).
-
-Type
-
- make install
-
-to install QEMU in /usr/local
-
-Tested tool versions
---------------------
-
-In order to compile QEMU succesfully, it is very important that you
-have the right tools. The most important one is gcc. I cannot guaranty
-that QEMU works if you do not use a tested gcc version. Look at
-'configure' and 'Makefile' if you want to make a different gcc
-version work.
-
-host gcc binutils glibc linux distribution
-----------------------------------------------------------------------
-x86 2.95.2 2.13.2 2.1.3 2.4.18
- 3.2 2.13.2 2.1.3 2.4.18
- 2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3
- 3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9
-
-PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq
- 3.2
-
-Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0
-
-Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0
-
-ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0
-
-[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
- for gcc version >= 3.3.
-[2] Linux >= 2.4.20 is necessary for precise exception support
- (untested).
-[3] 2.4.9-ac10-rmk2-np1-cerf2
-
-[4] gcc 2.95.x generates invalid code when using too many register
-variables. You must use gcc 3.x on PowerPC.
-
-Documentation
--------------
-
Read the documentation in qemu-doc.html.
-
Fabrice Bellard.
\ No newline at end of file
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/TODO
--- a/tools/ioemu/TODO Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/TODO Tue Aug 01 16:51:03 2006 -0400
@@ -1,20 +1,19 @@ short term:
short term:
----------
+- support variable tsc freq
+- cpu_interrupt() win32/SMP fix
+- USB host async
+- IDE async
- debug option in 'configure' script + disable -fomit-frame-pointer
-- Solaris display error with Cirrus VGA
- (http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00390.html).
- Precise VGA timings for old games/demos (malc patch)
- merge PIC spurious interrupt patch
-- merge VNC keyboard patch
- merge Solaris patch
-- merge ARM patches + self modifying code patch (Paul Brook)
-- warning for OS/2: must not use 128 MB memory
+- 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
-- test sysenter/sysexit and fxsr for L4 pistachio 686
- 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.
@@ -33,34 +32,30 @@ short term:
- 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)
-- SMP support
ppc specific:
------------
- TLB invalidate not needed if msr_pr changes
-- endianness bugs in do_load_fpscr and do_store_fpscr
- SPR_ENCODE() not useful
- enable shift optimizations ?
-lower priority:
---------------
-- more friendly BIOS (logo)
-- int15 ah=86: use better timing
-- HDD geometry in CMOS (not used except for very old DOS programs)
-- suppress shift_mem ops
-- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
-- sysenter/sysexit emulation
-- optimize FPU operations (evaluate x87 stack pointer statically)
+linux-user specific:
+-------------------
- add IPC syscalls
-- use -msoft-float on ARM
-- use kernel traps for unaligned accesses on ARM ?
- handle rare page fault cases (in particular if page fault in helpers or
in syscall emulation code).
-- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit
issues, fix 16 bit uid issues)
- use page_unprotect_range in every suitable syscall to handle all
cases of self modifying code.
-- use gcc as a backend to generate better code (easy to do by using
- op-i386.c operations as local inline functions).
-- add SSE2/MMX operations
+- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
+- use kernel traps for unaligned accesses on ARM ?
+
+
+lower priority:
+--------------
+- int15 ah=86: use better timing
+- suppress shift_mem ops
+- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
+- optimize FPU operations (evaluate x87 stack pointer statically)
+- use -msoft-float on ARM
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/VERSION
--- a/tools/ioemu/VERSION Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/VERSION Tue Aug 01 16:51:03 2006 -0400
@@ -1,1 +1,1 @@ 0.6.1
-0.6.1
\ No newline at end of file
+0.8.1
\ No newline at end of file
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio.c
--- a/tools/ioemu/audio/audio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
* QEMU Audio subsystem
- *
- * Copyright (c) 2003-2004 Vassili Karpov (malc)
- *
+ *
+ * Copyright (c) 2003-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -21,34 +21,95 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include <assert.h>
#include "vl.h"
-#define USE_WAV_AUDIO
-
-#include "audio/audio_int.h"
-
-#define dolog(...) AUD_log ("audio", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
+#define AUDIO_CAP "audio"
+#include "audio_int.h"
+
+/* #define DEBUG_PLIVE */
+/* #define DEBUG_LIVE */
+/* #define DEBUG_OUT */
+
+#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
+
+static struct audio_driver *drvtab[] = {
+#ifdef CONFIG_OSS
+ &oss_audio_driver,
+#endif
+#ifdef CONFIG_ALSA
+ &alsa_audio_driver,
+#endif
+#ifdef CONFIG_COREAUDIO
+ &coreaudio_audio_driver,
+#endif
+#ifdef CONFIG_DSOUND
+ &dsound_audio_driver,
+#endif
+#ifdef CONFIG_FMOD
+ &fmod_audio_driver,
+#endif
+#ifdef CONFIG_SDL
+ &sdl_audio_driver,
+#endif
+ &no_audio_driver,
+ &wav_audio_driver
+};
+
+struct fixed_settings {
+ int enabled;
+ int nb_voices;
+ int greedy;
+ audsettings_t settings;
+};
+
+static struct {
+ struct fixed_settings fixed_out;
+ struct fixed_settings fixed_in;
+ union {
+ int hz;
+ int64_t ticks;
+ } period;
+ int plive;
+ int log_to_monitor;
+} conf = {
+ { /* DAC fixed settings */
+ 1, /* enabled */
+ 1, /* nb_voices */
+ 1, /* greedy */
+ {
+ 44100, /* freq */
+ 2, /* nchannels */
+ AUD_FMT_S16 /* fmt */
+ }
+ },
+
+ { /* ADC fixed settings */
+ 1, /* enabled */
+ 1, /* nb_voices */
+ 1, /* greedy */
+ {
+ 44100, /* freq */
+ 2, /* nchannels */
+ AUD_FMT_S16 /* fmt */
+ }
+ },
+
+ { 0 }, /* period */
+ 0, /* plive */
+ 0 /* log_to_monitor */
+};
+
+static AudioState glob_audio_state;
+
+volume_t nominal_volume = {
+ 0,
+#ifdef FLOAT_MIXENG
+ 1.0,
+ 1.0
#else
-#define ldebug(...)
-#endif
-
-#define QC_AUDIO_DRV "QEMU_AUDIO_DRV"
-#define QC_VOICES "QEMU_VOICES"
-#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
-#define QC_FIXED_FREQ "QEMU_FIXED_FREQ"
-
-static HWVoice *hw_voices;
-
-AudioState audio_state = {
- 1, /* use fixed settings */
- 44100, /* fixed frequency */
- 2, /* fixed channels */
- AUD_FMT_S16, /* fixed format */
- 1, /* number of hw voices */
- -1 /* voice size */
+ UINT_MAX,
+ UINT_MAX
+#endif
};
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
@@ -68,74 +129,419 @@ inline uint32_t lsbindex (uint32_t u)
return popcount ((u&-u)-1);
}
-int audio_get_conf_int (const char *key, int defval)
-{
- int val = defval;
+#ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED
+#error No its not
+#else
+int audio_bug (const char *funcname, int cond)
+{
+ if (cond) {
+ static int shown;
+
+ AUD_log (NULL, "Error a bug that was just triggered in %s\n",
funcname);
+ if (!shown) {
+ shown = 1;
+ AUD_log (NULL, "Save all your work and restart without audio\n");
+ AUD_log (NULL, "Please send bug report to malc@xxxxxxxxxxxxx\n");
+ AUD_log (NULL, "I am sorry\n");
+ }
+ AUD_log (NULL, "Context:\n");
+
+#if defined AUDIO_BREAKPOINT_ON_BUG
+# if defined HOST_I386
+# if defined __GNUC__
+ __asm__ ("int3");
+# elif defined _MSC_VER
+ _asm _emit 0xcc;
+# else
+ abort ();
+# endif
+# else
+ abort ();
+# endif
+#endif
+ }
+
+ return cond;
+}
+#endif
+
+void *audio_calloc (const char *funcname, int nmemb, size_t size)
+{
+ int cond;
+ size_t len;
+
+ len = nmemb * size;
+ cond = !nmemb || !size;
+ cond |= nmemb < 0;
+ cond |= len < size;
+
+ if (audio_bug ("audio_calloc", cond)) {
+ AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
+ funcname);
+ AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len);
+ return NULL;
+ }
+
+ return qemu_mallocz (len);
+}
+
+static char *audio_alloc_prefix (const char *s)
+{
+ const char qemu_prefix[] = "QEMU_";
+ size_t len;
+ char *r;
+
+ if (!s) {
+ return NULL;
+ }
+
+ len = strlen (s);
+ r = qemu_malloc (len + sizeof (qemu_prefix));
+
+ if (r) {
+ size_t i;
+ char *u = r + sizeof (qemu_prefix) - 1;
+
+ strcpy (r, qemu_prefix);
+ strcat (r, s);
+
+ for (i = 0; i < len; ++i) {
+ u[i] = toupper (u[i]);
+ }
+ }
+ return r;
+}
+
+const char *audio_audfmt_to_string (audfmt_e fmt)
+{
+ switch (fmt) {
+ case AUD_FMT_U8:
+ return "U8";
+
+ case AUD_FMT_U16:
+ return "U16";
+
+ case AUD_FMT_S8:
+ return "S8";
+
+ case AUD_FMT_S16:
+ return "S16";
+ }
+
+ dolog ("Bogus audfmt %d returning S16\n", fmt);
+ return "S16";
+}
+
+audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
+{
+ if (!strcasecmp (s, "u8")) {
+ *defaultp = 0;
+ return AUD_FMT_U8;
+ }
+ else if (!strcasecmp (s, "u16")) {
+ *defaultp = 0;
+ return AUD_FMT_U16;
+ }
+ else if (!strcasecmp (s, "s8")) {
+ *defaultp = 0;
+ return AUD_FMT_S8;
+ }
+ else if (!strcasecmp (s, "s16")) {
+ *defaultp = 0;
+ return AUD_FMT_S16;
+ }
+ else {
+ dolog ("Bogus audio format `%s' using %s\n",
+ s, audio_audfmt_to_string (defval));
+ *defaultp = 1;
+ return defval;
+ }
+}
+
+static audfmt_e audio_get_conf_fmt (const char *envname,
+ audfmt_e defval,
+ int *defaultp)
+{
+ const char *var = getenv (envname);
+ if (!var) {
+ *defaultp = 1;
+ return defval;
+ }
+ return audio_string_to_audfmt (var, defval, defaultp);
+}
+
+static int audio_get_conf_int (const char *key, int defval, int *defaultp)
+{
+ int val;
char *strval;
strval = getenv (key);
if (strval) {
+ *defaultp = 0;
val = atoi (strval);
- }
-
- return val;
-}
-
-const char *audio_get_conf_str (const char *key, const char *defval)
+ return val;
+ }
+ else {
+ *defaultp = 1;
+ return defval;
+ }
+}
+
+static const char *audio_get_conf_str (const char *key,
+ const char *defval,
+ int *defaultp)
{
const char *val = getenv (key);
- if (!val)
+ if (!val) {
+ *defaultp = 1;
return defval;
- else
+ }
+ else {
+ *defaultp = 0;
return val;
+ }
+}
+
+void AUD_vlog (const char *cap, const char *fmt, va_list ap)
+{
+ if (conf.log_to_monitor) {
+ if (cap) {
+ term_printf ("%s: ", cap);
+ }
+
+ term_vprintf (fmt, ap);
+ }
+ else {
+ if (cap) {
+ fprintf (stderr, "%s: ", cap);
+ }
+
+ vfprintf (stderr, fmt, ap);
+ }
}
void AUD_log (const char *cap, const char *fmt, ...)
{
va_list ap;
- fprintf (stderr, "%s: ", cap);
+
va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
+ AUD_vlog (cap, fmt, ap);
va_end (ap);
}
-/*
- * Soft Voice
- */
-void pcm_sw_free_resources (SWVoice *sw)
-{
- if (sw->buf) qemu_free (sw->buf);
- if (sw->rate) st_rate_stop (sw->rate);
- sw->buf = NULL;
- sw->rate = NULL;
-}
-
-int pcm_sw_alloc_resources (SWVoice *sw)
-{
- sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
- if (!sw->buf)
+static void audio_print_options (const char *prefix,
+ struct audio_option *opt)
+{
+ char *uprefix;
+
+ if (!prefix) {
+ dolog ("No prefix specified\n");
+ return;
+ }
+
+ if (!opt) {
+ dolog ("No options\n");
+ return;
+ }
+
+ uprefix = audio_alloc_prefix (prefix);
+
+ for (; opt->name; opt++) {
+ const char *state = "default";
+ printf (" %s_%s: ", uprefix, opt->name);
+
+ if (opt->overridenp && *opt->overridenp) {
+ state = "current";
+ }
+
+ switch (opt->tag) {
+ case AUD_OPT_BOOL:
+ {
+ int *intp = opt->valp;
+ printf ("boolean, %s = %d\n", state, *intp ? 1 : 0);
+ }
+ break;
+
+ case AUD_OPT_INT:
+ {
+ int *intp = opt->valp;
+ printf ("integer, %s = %d\n", state, *intp);
+ }
+ break;
+
+ case AUD_OPT_FMT:
+ {
+ audfmt_e *fmtp = opt->valp;
+ printf (
+ "format, %s = %s, (one of: U8 S8 U16 S16)\n",
+ state,
+ audio_audfmt_to_string (*fmtp)
+ );
+ }
+ break;
+
+ case AUD_OPT_STR:
+ {
+ const char **strp = opt->valp;
+ printf ("string, %s = %s\n",
+ state,
+ *strp ? *strp : "(not set)");
+ }
+ break;
+
+ default:
+ printf ("???\n");
+ dolog ("Bad value tag for option %s_%s %d\n",
+ uprefix, opt->name, opt->tag);
+ break;
+ }
+ printf (" %s\n", opt->descr);
+ }
+
+ qemu_free (uprefix);
+}
+
+static void audio_process_options (const char *prefix,
+ struct audio_option *opt)
+{
+ char *optname;
+ const char qemu_prefix[] = "QEMU_";
+ size_t preflen;
+
+ if (audio_bug (AUDIO_FUNC, !prefix)) {
+ dolog ("prefix = NULL\n");
+ return;
+ }
+
+ if (audio_bug (AUDIO_FUNC, !opt)) {
+ dolog ("opt = NULL\n");
+ return;
+ }
+
+ preflen = strlen (prefix);
+
+ for (; opt->name; opt++) {
+ size_t len, i;
+ int def;
+
+ if (!opt->valp) {
+ dolog ("Option value pointer for `%s' is not set\n",
+ opt->name);
+ continue;
+ }
+
+ len = strlen (opt->name);
+ /* len of opt->name + len of prefix + size of qemu_prefix
+ * (includes trailing zero) + zero + underscore (on behalf of
+ * sizeof) */
+ optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1);
+ if (!optname) {
+ dolog ("Could not allocate memory for option name `%s'\n",
+ opt->name);
+ continue;
+ }
+
+ strcpy (optname, qemu_prefix);
+
+ /* copy while upper-casing, including trailing zero */
+ for (i = 0; i <= preflen; ++i) {
+ optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
+ }
+ strcat (optname, "_");
+ strcat (optname, opt->name);
+
+ def = 1;
+ switch (opt->tag) {
+ case AUD_OPT_BOOL:
+ case AUD_OPT_INT:
+ {
+ int *intp = opt->valp;
+ *intp = audio_get_conf_int (optname, *intp, &def);
+ }
+ break;
+
+ case AUD_OPT_FMT:
+ {
+ audfmt_e *fmtp = opt->valp;
+ *fmtp = audio_get_conf_fmt (optname, *fmtp, &def);
+ }
+ break;
+
+ case AUD_OPT_STR:
+ {
+ const char **strp = opt->valp;
+ *strp = audio_get_conf_str (optname, *strp, &def);
+ }
+ break;
+
+ default:
+ dolog ("Bad value tag for option `%s' - %d\n",
+ optname, opt->tag);
+ break;
+ }
+
+ if (!opt->overridenp) {
+ opt->overridenp = &opt->overriden;
+ }
+ *opt->overridenp = !def;
+ qemu_free (optname);
+ }
+}
+
+static void audio_print_settings (audsettings_t *as)
+{
+ dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
+
+ switch (as->fmt) {
+ case AUD_FMT_S8:
+ AUD_log (NULL, "S8");
+ break;
+ case AUD_FMT_U8:
+ AUD_log (NULL, "U8");
+ break;
+ case AUD_FMT_S16:
+ AUD_log (NULL, "S16");
+ break;
+ case AUD_FMT_U16:
+ AUD_log (NULL, "U16");
+ break;
+ default:
+ AUD_log (NULL, "invalid(%d)", as->fmt);
+ break;
+ }
+ AUD_log (NULL, "\n");
+}
+
+static int audio_validate_settigs (audsettings_t *as)
+{
+ int invalid;
+
+ invalid = as->nchannels != 1 && as->nchannels != 2;
+
+ switch (as->fmt) {
+ case AUD_FMT_S8:
+ case AUD_FMT_U8:
+ case AUD_FMT_S16:
+ case AUD_FMT_U16:
+ break;
+ default:
+ invalid = 1;
+ break;
+ }
+
+ invalid |= as->freq <= 0;
+
+ if (invalid) {
return -1;
-
- sw->rate = st_rate_start (sw->freq, sw->hw->freq);
- if (!sw->rate) {
- qemu_free (sw->buf);
- sw->buf = NULL;
- return -1;
}
return 0;
}
-void pcm_sw_fini (SWVoice *sw)
-{
- pcm_sw_free_resources (sw);
-}
-
-int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
- int nchannels, audfmt_e fmt)
+static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
{
int bits = 8, sign = 0;
- switch (fmt) {
+ switch (as->fmt) {
case AUD_FMT_S8:
sign = 1;
case AUD_FMT_U8:
@@ -147,626 +553,428 @@ int pcm_sw_init (SWVoice *sw, HWVoice *h
bits = 16;
break;
}
-
- sw->hw = hw;
- sw->freq = freq;
- sw->fmt = fmt;
- sw->nchannels = nchannels;
- sw->shift = (nchannels == 2) + (bits == 16);
- sw->align = (1 << sw->shift) - 1;
- sw->left = 0;
- sw->pos = 0;
- sw->wpos = 0;
- sw->live = 0;
- sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
- sw->bytes_per_second = sw->freq << sw->shift;
- sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
-
- pcm_sw_free_resources (sw);
- return pcm_sw_alloc_resources (sw);
-}
-
-/* Hard voice */
-void pcm_hw_free_resources (HWVoice *hw)
-{
- if (hw->mix_buf)
- qemu_free (hw->mix_buf);
- hw->mix_buf = NULL;
-}
-
-int pcm_hw_alloc_resources (HWVoice *hw)
-{
- hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
- if (!hw->mix_buf)
- return -1;
- return 0;
-}
-
-void pcm_hw_fini (HWVoice *hw)
-{
- if (hw->active) {
- ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
- pcm_hw_free_resources (hw);
- hw->pcm_ops->fini (hw);
- memset (hw, 0, audio_state.drv->voice_size);
- }
-}
-
-void pcm_hw_gc (HWVoice *hw)
-{
- if (hw->nb_voices)
+ 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
+ )
+{
+ int bits = 8, sign = 0;
+
+ switch (as->fmt) {
+ case AUD_FMT_S8:
+ sign = 1;
+ case AUD_FMT_U8:
+ break;
+
+ case AUD_FMT_S16:
+ sign = 1;
+ case AUD_FMT_U16:
+ bits = 16;
+ break;
+ }
+
+ info->freq = as->freq;
+ info->bits = bits;
+ info->sign = sign;
+ info->nchannels = as->nchannels;
+ 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;
+}
+
+void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
+{
+ if (!len) {
return;
-
- pcm_hw_fini (hw);
-}
-
-int pcm_hw_get_live (HWVoice *hw)
-{
- int i, alive = 0, live = hw->samples;
-
- for (i = 0; i < hw->nb_voices; i++) {
- if (hw->pvoice[i]->live) {
- live = audio_MIN (hw->pvoice[i]->live, live);
- alive += 1;
- }
- }
-
- if (alive)
+ }
+
+ if (info->sign) {
+ memset (buf, len << info->shift, 0x00);
+ }
+ else {
+ if (info->bits == 8) {
+ memset (buf, len << info->shift, 0x80);
+ }
+ else {
+ int i;
+ uint16_t *p = buf;
+ int shift = info->nchannels - 1;
+ short s = INT16_MAX;
+
+ if (info->swap_endian) {
+ s = bswap16 (s);
+ }
+
+ for (i = 0; i < len << shift; i++) {
+ p[i] = s;
+ }
+ }
+ }
+}
+
+/*
+ * Hard voice (capture)
+ */
+static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)
+{
+ SWVoiceIn *sw;
+ int m = hw->total_samples_captured;
+
+ for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+ if (sw->active) {
+ m = audio_MIN (m, sw->total_hw_samples_acquired);
+ }
+ }
+ return m;
+}
+
+int audio_pcm_hw_get_live_in (HWVoiceIn *hw)
+{
+ int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live=%d hw->samples=%d\n", live, hw->samples);
+ return 0;
+ }
+ return live;
+}
+
+/*
+ * Soft voice (capture)
+ */
+static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)
+{
+ HWVoiceIn *hw = sw->hw;
+ int live = hw->total_samples_captured - sw->total_hw_samples_acquired;
+ int rpos;
+
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live=%d hw->samples=%d\n", live, hw->samples);
+ return 0;
+ }
+
+ rpos = hw->wpos - live;
+ if (rpos >= 0) {
+ return rpos;
+ }
+ else {
+ return hw->samples + rpos;
+ }
+}
+
+int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
+{
+ HWVoiceIn *hw = sw->hw;
+ int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
+ st_sample_t *src, *dst = sw->buf;
+
+ rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
+
+ live = hw->total_samples_captured - sw->total_hw_samples_acquired;
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live_in=%d hw->samples=%d\n", live, hw->samples);
+ return 0;
+ }
+
+ samples = size >> sw->info.shift;
+ if (!live) {
+ return 0;
+ }
+
+ swlim = (live * sw->ratio) >> 32;
+ swlim = audio_MIN (swlim, samples);
+
+ while (swlim) {
+ src = hw->conv_buf + rpos;
+ isamp = hw->wpos - rpos;
+ /* XXX: <= ? */
+ if (isamp <= 0) {
+ isamp = hw->samples - rpos;
+ }
+
+ if (!isamp) {
+ break;
+ }
+ osamp = swlim;
+
+ if (audio_bug (AUDIO_FUNC, osamp < 0)) {
+ dolog ("osamp=%d\n", osamp);
+ return 0;
+ }
+
+ st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
+ swlim -= osamp;
+ rpos = (rpos + isamp) % hw->samples;
+ dst += osamp;
+ ret += osamp;
+ total += isamp;
+ }
+
+ sw->clip (buf, sw->buf, ret);
+ sw->total_hw_samples_acquired += total;
+ return ret << sw->info.shift;
+}
+
+/*
+ * Hard voice (playback)
+ */
+static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
+{
+ SWVoiceOut *sw;
+ int m = INT_MAX;
+ int nb_live = 0;
+
+ for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+ if (sw->active || !sw->empty) {
+ m = audio_MIN (m, sw->total_hw_samples_mixed);
+ nb_live += 1;
+ }
+ }
+
+ *nb_livep = nb_live;
+ return m;
+}
+
+int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live)
+{
+ int smin;
+
+ smin = audio_pcm_hw_find_min_out (hw, nb_live);
+
+ if (!*nb_live) {
+ return 0;
+ }
+ else {
+ int live = smin;
+
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live=%d hw->samples=%d\n", live, hw->samples);
+ return 0;
+ }
return live;
- else
- return -1;
-}
-
-int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
-{
- int i, alive = 0, live = hw->samples;
-
- *nb_active = 0;
- for (i = 0; i < hw->nb_voices; i++) {
- if (hw->pvoice[i]->live) {
- if (hw->pvoice[i]->live < live) {
- *nb_active = hw->pvoice[i]->active != 0;
- live = hw->pvoice[i]->live;
- }
- alive += 1;
- }
- }
-
- if (alive)
- return live;
- else
- return -1;
-}
-
-void pcm_hw_dec_live (HWVoice *hw, int decr)
-{
- int i;
-
- for (i = 0; i < hw->nb_voices; i++) {
- if (hw->pvoice[i]->live) {
- hw->pvoice[i]->live -= decr;
- }
- }
-}
-
-void pcm_hw_clear (HWVoice *hw, void *buf, int len)
-{
- if (!len)
- return;
-
- switch (hw->fmt) {
- case AUD_FMT_S16:
- case AUD_FMT_S8:
- memset (buf, 0x00, len << hw->shift);
- break;
-
- case AUD_FMT_U8:
- memset (buf, 0x80, len << hw->shift);
- break;
-
- case AUD_FMT_U16:
- {
- unsigned int i;
- uint16_t *p = buf;
- int shift = hw->nchannels - 1;
-
- for (i = 0; i < len << shift; i++) {
- p[i] = INT16_MAX;
- }
- }
- break;
- }
-}
-
-int pcm_hw_write (SWVoice *sw, void *buf, int size)
+ }
+}
+
+int audio_pcm_hw_get_live_out (HWVoiceOut *hw)
+{
+ int nb_live;
+ int live;
+
+ live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live=%d hw->samples=%d\n", live, hw->samples);
+ return 0;
+ }
+ return live;
+}
+
+/*
+ * Soft voice (playback)
+ */
+int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
{
int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
- int ret = 0, pos = 0;
- if (!sw)
+ int ret = 0, pos = 0, total = 0;
+
+ if (!sw) {
return size;
+ }
hwsamples = sw->hw->samples;
- samples = size >> sw->shift;
-
- if (!sw->live) {
- sw->wpos = sw->hw->rpos;
- }
- wpos = sw->wpos;
- live = sw->live;
+
+ live = sw->total_hw_samples_mixed;
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){
+ dolog ("live=%d hw->samples=%d\n", live, hwsamples);
+ return 0;
+ }
+
+ if (live == hwsamples) {
+ return 0;
+ }
+
+ wpos = (sw->hw->rpos + live) % hwsamples;
+ samples = size >> sw->info.shift;
+
dead = hwsamples - live;
- swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
+ swlim = ((int64_t) dead << 32) / sw->ratio;
swlim = audio_MIN (swlim, samples);
-
- ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
- size, live, dead, swlim, wpos);
- if (swlim)
- sw->conv (sw->buf, buf, swlim);
+ if (swlim) {
+ sw->conv (sw->buf, buf, swlim, &sw->vol);
+ }
while (swlim) {
dead = hwsamples - live;
left = hwsamples - wpos;
blck = audio_MIN (dead, left);
if (!blck) {
- /* dolog ("swlim=%d\n", swlim); */
break;
}
isamp = swlim;
osamp = blck;
- st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp,
&osamp);
+ st_rate_flow_mix (
+ sw->rate,
+ sw->buf + pos,
+ sw->hw->mix_buf + wpos,
+ &isamp,
+ &osamp
+ );
ret += isamp;
swlim -= isamp;
pos += isamp;
live += osamp;
wpos = (wpos + osamp) % hwsamples;
- }
-
- sw->wpos = wpos;
- sw->live = live;
- return ret << sw->shift;
-}
-
-int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
-{
- int sign = 0, bits = 8;
-
- pcm_hw_fini (hw);
- ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
- if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
- memset (hw, 0, audio_state.drv->voice_size);
- return -1;
- }
-
- switch (hw->fmt) {
- case AUD_FMT_S8:
- sign = 1;
- case AUD_FMT_U8:
- break;
-
- case AUD_FMT_S16:
- sign = 1;
- case AUD_FMT_U16:
- bits = 16;
- break;
- }
-
- hw->nb_voices = 0;
- hw->active = 1;
- hw->shift = (hw->nchannels == 2) + (bits == 16);
- hw->bytes_per_second = hw->freq << hw->shift;
- hw->align = (1 << hw->shift) - 1;
- hw->samples = hw->bufsize >> hw->shift;
- hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
- if (pcm_hw_alloc_resources (hw)) {
- pcm_hw_fini (hw);
- return -1;
- }
- return 0;
-}
-
-static int dist (void *hw)
-{
- if (hw) {
- return (((uint8_t *) hw - (uint8_t *) hw_voices)
- / audio_state.voice_size) + 1;
- }
- else {
- return 0;
- }
-}
-
-#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices
-
-HWVoice *pcm_hw_find_any (HWVoice *hw)
-{
- int i = dist (hw);
- for (; i < audio_state.nb_hw_voices; i++) {
- hw = ADVANCE (hw);
- return hw;
- }
- return NULL;
-}
-
-HWVoice *pcm_hw_find_any_active (HWVoice *hw)
-{
- int i = dist (hw);
- for (; i < audio_state.nb_hw_voices; i++) {
- hw = ADVANCE (hw);
- if (hw->active)
- return hw;
- }
- return NULL;
-}
-
-HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
-{
- int i = dist (hw);
- for (; i < audio_state.nb_hw_voices; i++) {
- hw = ADVANCE (hw);
- if (hw->active && hw->enabled)
- return hw;
- }
- return NULL;
-}
-
-HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
-{
- int i = dist (hw);
- for (; i < audio_state.nb_hw_voices; i++) {
- hw = ADVANCE (hw);
- if (!hw->active)
- return hw;
- }
- return NULL;
-}
-
-HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
- int nchannels, audfmt_e fmt)
-{
- while ((hw = pcm_hw_find_any_active (hw))) {
- if (hw->freq == freq &&
- hw->nchannels == nchannels &&
- hw->fmt == fmt)
- return hw;
- }
- return NULL;
-}
-
-HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
-{
- HWVoice *hw;
-
- if (audio_state.fixed_format) {
- freq = audio_state.fixed_freq;
- nchannels = audio_state.fixed_channels;
- fmt = audio_state.fixed_fmt;
- }
-
- hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
-
- if (hw)
- return hw;
-
- hw = pcm_hw_find_any_passive (NULL);
- if (hw) {
- hw->pcm_ops = audio_state.drv->pcm_ops;
- if (!hw->pcm_ops)
- return NULL;
-
- if (pcm_hw_init (hw, freq, nchannels, fmt)) {
- pcm_hw_gc (hw);
- return NULL;
- }
- else
- return hw;
- }
-
- return pcm_hw_find_any (NULL);
-}
-
-int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
-{
- SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
- if (!pvoice)
- return -1;
-
- memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
- qemu_free (hw->pvoice);
- hw->pvoice = pvoice;
- hw->pvoice[hw->nb_voices++] = sw;
- return 0;
-}
-
-int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
-{
- int i, j;
- if (hw->nb_voices > 1) {
- SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
-
- if (!pvoice) {
- dolog ("Can not maintain consistent state (not enough memory)\n");
- return -1;
- }
-
- for (i = 0, j = 0; i < hw->nb_voices; i++) {
- if (j >= hw->nb_voices - 1) {
- dolog ("Can not maintain consistent state "
- "(invariant violated)\n");
- return -1;
- }
- if (hw->pvoice[i] != sw)
- pvoice[j++] = hw->pvoice[i];
- }
- qemu_free (hw->pvoice);
- hw->pvoice = pvoice;
- hw->nb_voices -= 1;
- }
- else {
- qemu_free (hw->pvoice);
- hw->pvoice = NULL;
- hw->nb_voices = 0;
- }
- return 0;
-}
-
-SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
-{
- SWVoice *sw;
- HWVoice *hw;
-
- sw = qemu_mallocz (sizeof (*sw));
- if (!sw)
- goto err1;
-
- hw = pcm_hw_add (freq, nchannels, fmt);
- if (!hw)
- goto err2;
-
- if (pcm_hw_add_sw (hw, sw))
- goto err3;
-
- if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
- goto err4;
-
- return sw;
-
-err4:
- pcm_hw_del_sw (hw, sw);
-err3:
- pcm_hw_gc (hw);
-err2:
- qemu_free (sw);
-err1:
- return NULL;
-}
-
-SWVoice *AUD_open (SWVoice *sw, const char *name,
- int freq, int nchannels, audfmt_e fmt)
-{
- if (!audio_state.drv) {
- return NULL;
- }
-
- if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt ==
fmt) {
- return sw;
- }
-
- if (sw) {
- ldebug ("Different format %s %d %d %d\n",
- name,
- sw->freq == freq,
- sw->nchannels == nchannels,
- sw->fmt == fmt);
- }
-
- if (nchannels != 1 && nchannels != 2) {
- dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
- return NULL;
- }
-
- if (!audio_state.fixed_format && sw) {
- pcm_sw_fini (sw);
- pcm_hw_del_sw (sw->hw, sw);
- pcm_hw_gc (sw->hw);
- if (sw->name) {
- qemu_free (sw->name);
- sw->name = NULL;
- }
- qemu_free (sw);
- sw = NULL;
- }
-
- if (sw) {
- HWVoice *hw = sw->hw;
- if (!hw) {
- dolog ("Internal logic error voice %s has no hardware store\n",
- name);
- return sw;
- }
-
- if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
- pcm_sw_fini (sw);
- pcm_hw_del_sw (hw, sw);
- pcm_hw_gc (hw);
- if (sw->name) {
- qemu_free (sw->name);
- sw->name = NULL;
- }
- qemu_free (sw);
- return NULL;
- }
- }
- else {
- sw = pcm_create_voice_pair (freq, nchannels, fmt);
- if (!sw) {
- dolog ("Failed to create voice %s\n", name);
- return NULL;
- }
- }
-
- if (sw->name) {
- qemu_free (sw->name);
- sw->name = NULL;
- }
- sw->name = qemu_strdup (name);
- return sw;
-}
-
-void AUD_close (SWVoice *sw)
-{
- if (!sw)
- return;
-
- pcm_sw_fini (sw);
- pcm_hw_del_sw (sw->hw, sw);
- pcm_hw_gc (sw->hw);
- if (sw->name) {
- qemu_free (sw->name);
- sw->name = NULL;
- }
- qemu_free (sw);
-}
-
-int AUD_write (SWVoice *sw, void *buf, int size)
+ total += osamp;
+ }
+
+ sw->total_hw_samples_mixed += total;
+ sw->empty = sw->total_hw_samples_mixed == 0;
+
+#ifdef DEBUG_OUT
+ dolog (
+ "%s: write size %d ret %d total sw %d\n",
+ SW_NAME (sw),
+ size >> sw->info.shift,
+ ret,
+ sw->total_hw_samples_mixed
+ );
+#endif
+
+ return ret << sw->info.shift;
+}
+
+#ifdef DEBUG_AUDIO
+static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
+{
+ dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",
+ cap, info->bits, info->sign, info->freq, info->nchannels);
+}
+#endif
+
+#define DAC
+#include "audio_template.h"
+#undef DAC
+#include "audio_template.h"
+
+int AUD_write (SWVoiceOut *sw, void *buf, int size)
{
int bytes;
- if (!sw->hw->enabled)
- dolog ("Writing to disabled voice %s\n", sw->name);
+ if (!sw) {
+ /* XXX: Consider options */
+ return size;
+ }
+
+ if (!sw->hw->enabled) {
+ dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
+ return 0;
+ }
+
bytes = sw->hw->pcm_ops->write (sw, buf, size);
return bytes;
}
-void AUD_run (void)
-{
- HWVoice *hw = NULL;
-
- while ((hw = pcm_hw_find_any_active_enabled (hw))) {
- int i;
- if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
- hw->enabled = 0;
- hw->pcm_ops->ctl (hw, VOICE_DISABLE);
- for (i = 0; i < hw->nb_voices; i++) {
- hw->pvoice[i]->live = 0;
- /* hw->pvoice[i]->old_ticks = 0; */
- }
- continue;
- }
-
- hw->pcm_ops->run (hw);
- assert (hw->rpos < hw->samples);
- for (i = 0; i < hw->nb_voices; i++) {
- SWVoice *sw = hw->pvoice[i];
- if (!sw->active && !sw->live && sw->old_ticks) {
- int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
- if (delta > audio_state.ticks_threshold) {
- ldebug ("resetting old_ticks for %s\n", sw->name);
- sw->old_ticks = 0;
- }
- }
- }
- }
-}
-
-int AUD_get_free (SWVoice *sw)
-{
- int free;
-
- if (!sw)
- return 4096;
-
- free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
- / INT_MAX;
-
- free &= ~sw->hw->align;
- if (!free) return 0;
-
- return free;
-}
-
-int AUD_get_buffer_size (SWVoice *sw)
-{
- return sw->hw->bufsize;
-}
-
-void AUD_adjust (SWVoice *sw, int bytes)
-{
- if (!sw)
+int AUD_read (SWVoiceIn *sw, void *buf, int size)
+{
+ int bytes;
+
+ if (!sw) {
+ /* XXX: Consider options */
+ return size;
+ }
+
+ if (!sw->hw->enabled) {
+ dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
+ return 0;
+ }
+
+ bytes = sw->hw->pcm_ops->read (sw, buf, size);
+ return bytes;
+}
+
+int AUD_get_buffer_size_out (SWVoiceOut *sw)
+{
+ return sw->hw->samples << sw->hw->info.shift;
+}
+
+void AUD_set_active_out (SWVoiceOut *sw, int on)
+{
+ HWVoiceOut *hw;
+
+ if (!sw) {
return;
- sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
-}
-
-void AUD_reset (SWVoice *sw)
-{
- sw->active = 0;
- sw->old_ticks = 0;
-}
-
-int AUD_calc_elapsed (SWVoice *sw)
-{
- int64_t now, delta, bytes;
- int dead, swlim;
-
- if (!sw)
- return 0;
-
- now = qemu_get_clock (vm_clock);
- delta = now - sw->old_ticks;
- bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
- if (delta < 0) {
- dolog ("whoops delta(<0)=%"PRId64"\n", delta);
- return 0;
- }
-
- dead = sw->hw->samples - sw->live;
- swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
-
- if (bytes > swlim) {
- return swlim;
- }
- else {
- return bytes;
- }
-}
-
-void AUD_enable (SWVoice *sw, int on)
-{
- int i;
- HWVoice *hw;
-
- if (!sw)
- return;
+ }
hw = sw->hw;
- if (on) {
- if (!sw->live)
- sw->wpos = sw->hw->rpos;
- if (!sw->old_ticks) {
- sw->old_ticks = qemu_get_clock (vm_clock);
- }
- }
-
if (sw->active != on) {
+ SWVoiceOut *temp_sw;
+
if (on) {
+ int total;
+
hw->pending_disable = 0;
if (!hw->enabled) {
hw->enabled = 1;
- for (i = 0; i < hw->nb_voices; i++) {
- ldebug ("resetting voice\n");
- sw = hw->pvoice[i];
- sw->old_ticks = qemu_get_clock (vm_clock);
+ hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
+ }
+
+ if (sw->empty) {
+ total = 0;
+ }
+ }
+ else {
+ if (hw->enabled) {
+ int nb_active = 0;
+
+ for (temp_sw = hw->sw_head.lh_first; temp_sw;
+ temp_sw = temp_sw->entries.le_next) {
+ nb_active += temp_sw->active != 0;
}
- hw->pcm_ops->ctl (hw, VOICE_ENABLE);
- }
+
+ hw->pending_disable = nb_active == 1;
+ }
+ }
+ sw->active = on;
+ }
+}
+
+void AUD_set_active_in (SWVoiceIn *sw, int on)
+{
+ HWVoiceIn *hw;
+
+ if (!sw) {
+ return;
+ }
+
+ hw = sw->hw;
+ if (sw->active != on) {
+ SWVoiceIn *temp_sw;
+
+ if (on) {
+ if (!hw->enabled) {
+ hw->enabled = 1;
+ hw->pcm_ops->ctl_in (hw, VOICE_ENABLE);
+ }
+ sw->total_hw_samples_acquired = hw->total_samples_captured;
}
else {
- if (hw->enabled && !hw->pending_disable) {
+ if (hw->enabled) {
int nb_active = 0;
- for (i = 0; i < hw->nb_voices; i++) {
- nb_active += hw->pvoice[i]->active != 0;
+
+ for (temp_sw = hw->sw_head.lh_first; temp_sw;
+ temp_sw = temp_sw->entries.le_next) {
+ nb_active += temp_sw->active != 0;
}
if (nb_active == 1) {
- hw->pending_disable = 1;
+ hw->enabled = 0;
+ hw->pcm_ops->ctl_in (hw, VOICE_DISABLE);
}
}
}
@@ -774,137 +982,500 @@ void AUD_enable (SWVoice *sw, int on)
}
}
-static struct audio_output_driver *drvtab[] = {
-#ifdef CONFIG_OSS
- &oss_output_driver,
-#endif
-#ifdef CONFIG_FMOD
- &fmod_output_driver,
-#endif
-#ifdef CONFIG_SDL
- &sdl_output_driver,
-#endif
- &no_output_driver,
-#ifdef USE_WAV_AUDIO
- &wav_output_driver,
-#endif
+static int audio_get_avail (SWVoiceIn *sw)
+{
+ int live;
+
+ if (!sw) {
+ return 0;
+ }
+
+ live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
+ dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
+ return 0;
+ }
+
+ ldebug (
+ "%s: get_avail live %d ret %lld\n",
+ SW_NAME (sw),
+ live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
+ );
+
+ return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;
+}
+
+static int audio_get_free (SWVoiceOut *sw)
+{
+ int live, dead;
+
+ if (!sw) {
+ return 0;
+ }
+
+ live = sw->total_hw_samples_mixed;
+
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
+ dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
+ return 0;
+ }
+
+ dead = sw->hw->samples - live;
+
+#ifdef DEBUG_OUT
+ dolog ("%s: get_free live %d dead %d ret %lld\n",
+ SW_NAME (sw),
+ live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
+#endif
+
+ return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
+}
+
+static void audio_run_out (AudioState *s)
+{
+ HWVoiceOut *hw = NULL;
+ SWVoiceOut *sw;
+
+ while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
+ int played;
+ int live, free, nb_live, cleanup_required;
+
+ live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
+ if (!nb_live) {
+ live = 0;
+ }
+
+ if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
+ dolog ("live=%d hw->samples=%d\n", live, hw->samples);
+ continue;
+ }
+
+ if (hw->pending_disable && !nb_live) {
+#ifdef DEBUG_OUT
+ dolog ("Disabling voice\n");
+#endif
+ hw->enabled = 0;
+ hw->pending_disable = 0;
+ hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);
+ continue;
+ }
+
+ if (!live) {
+ for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+ if (sw->active) {
+ free = audio_get_free (sw);
+ if (free > 0) {
+ sw->callback.fn (sw->callback.opaque, free);
+ }
+ }
+ }
+ continue;
+ }
+
+ 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",
+ hw->rpos, hw->samples, played);
+ hw->rpos = 0;
+ }
+
+#ifdef DEBUG_OUT
+ dolog ("played=%d\n", played);
+#endif
+
+ if (played) {
+ hw->ts_helper += played;
+ }
+
+ cleanup_required = 0;
+ for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+ if (!sw->active && sw->empty) {
+ continue;
+ }
+
+ if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) {
+ dolog ("played=%d sw->total_hw_samples_mixed=%d\n",
+ played, sw->total_hw_samples_mixed);
+ played = sw->total_hw_samples_mixed;
+ }
+
+ sw->total_hw_samples_mixed -= played;
+
+ if (!sw->total_hw_samples_mixed) {
+ sw->empty = 1;
+ cleanup_required |= !sw->active && !sw->callback.fn;
+ }
+
+ if (sw->active) {
+ free = audio_get_free (sw);
+ if (free > 0) {
+ sw->callback.fn (sw->callback.opaque, free);
+ }
+ }
+ }
+
+ if (cleanup_required) {
+ restart:
+ for (sw = hw->sw_head.lh_first; sw; sw = 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 */
+ }
+ }
+ }
+ }
+}
+
+static void audio_run_in (AudioState *s)
+{
+ HWVoiceIn *hw = NULL;
+
+ while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {
+ SWVoiceIn *sw;
+ int captured, min;
+
+ captured = hw->pcm_ops->run_in (hw);
+
+ min = audio_pcm_hw_find_min_in (hw);
+ hw->total_samples_captured += captured - min;
+ hw->ts_helper += captured;
+
+ for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
+ sw->total_hw_samples_acquired -= min;
+
+ if (sw->active) {
+ int avail;
+
+ avail = audio_get_avail (sw);
+ if (avail > 0) {
+ sw->callback.fn (sw->callback.opaque, avail);
+ }
+ }
+ }
+ }
+}
+
+static void audio_timer (void *opaque)
+{
+ AudioState *s = opaque;
+
+ audio_run_out (s);
+ audio_run_in (s);
+
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
+}
+
+static struct audio_option audio_options[] = {
+ /* DAC */
+ {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
+ "Use fixed settings for host DAC", NULL, 0},
+
+ {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq,
+ "Frequency for fixed host DAC", NULL, 0},
+
+ {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt,
+ "Format for fixed host DAC", NULL, 0},
+
+ {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels,
+ "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},
+
+ {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices,
+ "Number of voices for DAC", NULL, 0},
+
+ /* ADC */
+ {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled,
+ "Use fixed settings for host ADC", NULL, 0},
+
+ {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq,
+ "Frequency for fixed host ADC", NULL, 0},
+
+ {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt,
+ "Format for fixed host ADC", NULL, 0},
+
+ {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels,
+ "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},
+
+ {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices,
+ "Number of voices for ADC", NULL, 0},
+
+ /* Misc */
+ {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hz,
+ "Timer period in HZ (0 - use lowest possible)", NULL, 0},
+
+ {"PLIVE", AUD_OPT_BOOL, &conf.plive,
+ "(undocumented)", NULL, 0},
+
+ {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,
+ "print logging messages to montior instead of stderr", NULL, 0},
+
+ {NULL, 0, NULL, NULL, NULL, 0}
};
-static int voice_init (struct audio_output_driver *drv)
-{
- audio_state.opaque = drv->init ();
- if (audio_state.opaque) {
- if (audio_state.nb_hw_voices > drv->max_voices) {
- dolog ("`%s' does not support %d multiple hardware channels\n"
- "Resetting to %d\n",
- drv->name, audio_state.nb_hw_voices, drv->max_voices);
- audio_state.nb_hw_voices = drv->max_voices;
- }
- hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
- if (hw_voices) {
- audio_state.drv = drv;
- return 1;
+static void audio_pp_nb_voices (const char *typ, int nb)
+{
+ switch (nb) {
+ case 0:
+ printf ("Does not support %s\n", typ);
+ break;
+ case 1:
+ printf ("One %s voice\n", typ);
+ break;
+ case INT_MAX:
+ printf ("Theoretically supports many %s voices\n", typ);
+ break;
+ default:
+ printf ("Theoretically supports upto %d %s voices\n", nb, typ);
+ break;
+ }
+
+}
+
+void AUD_help (void)
+{
+ size_t i;
+
+ audio_process_options ("AUDIO", audio_options);
+ for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+ struct audio_driver *d = drvtab[i];
+ if (d->options) {
+ audio_process_options (d->name, d->options);
+ }
+ }
+
+ printf ("Audio options:\n");
+ audio_print_options ("AUDIO", audio_options);
+ printf ("\n");
+
+ printf ("Available drivers:\n");
+
+ for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+ struct audio_driver *d = drvtab[i];
+
+ printf ("Name: %s\n", d->name);
+ printf ("Description: %s\n", d->descr);
+
+ audio_pp_nb_voices ("playback", d->max_voices_out);
+ audio_pp_nb_voices ("capture", d->max_voices_in);
+
+ if (d->options) {
+ printf ("Options:\n");
+ audio_print_options (d->name, d->options);
}
else {
- dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
- audio_state.nb_hw_voices, drv->name, drv->voice_size);
- drv->fini (audio_state.opaque);
- return 0;
- }
+ printf ("No options\n");
+ }
+ printf ("\n");
+ }
+
+ printf (
+ "Options are settable through environment variables.\n"
+ "Example:\n"
+#ifdef _WIN32
+ " set QEMU_AUDIO_DRV=wav\n"
+ " set QEMU_WAV_PATH=c:\\tune.wav\n"
+#else
+ " export QEMU_AUDIO_DRV=wav\n"
+ " export QEMU_WAV_PATH=$HOME/tune.wav\n"
+ "(for csh replace export with setenv in the above)\n"
+#endif
+ " qemu ...\n\n"
+ );
+}
+
+static int audio_driver_init (AudioState *s, struct audio_driver *drv)
+{
+ if (drv->options) {
+ audio_process_options (drv->name, drv->options);
+ }
+ s->drv_opaque = drv->init ();
+
+ if (s->drv_opaque) {
+ audio_init_nb_voices_out (s, drv);
+ audio_init_nb_voices_in (s, drv);
+ s->drv = drv;
+ return 0;
}
else {
- dolog ("Could not init `%s' audio\n", drv->name);
- return 0;
- }
-}
-
-static void audio_vm_stop_handler (void *opaque, int reason)
-{
- HWVoice *hw = NULL;
-
- while ((hw = pcm_hw_find_any (hw))) {
- if (!hw->pcm_ops)
- continue;
-
- hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
+ dolog ("Could not init `%s' audio driver\n", drv->name);
+ return -1;
+ }
+}
+
+static void audio_vm_change_state_handler (void *opaque, int running)
+{
+ AudioState *s = opaque;
+ HWVoiceOut *hwo = NULL;
+ HWVoiceIn *hwi = NULL;
+ int op = running ? VOICE_ENABLE : VOICE_DISABLE;
+
+ while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
+ hwo->pcm_ops->ctl_out (hwo, op);
+ }
+
+ while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
+ hwi->pcm_ops->ctl_in (hwi, op);
}
}
static void audio_atexit (void)
{
- HWVoice *hw = NULL;
-
- while ((hw = pcm_hw_find_any (hw))) {
- if (!hw->pcm_ops)
- continue;
-
- hw->pcm_ops->ctl (hw, VOICE_DISABLE);
- hw->pcm_ops->fini (hw);
- }
- audio_state.drv->fini (audio_state.opaque);
+ AudioState *s = &glob_audio_state;
+ HWVoiceOut *hwo = NULL;
+ HWVoiceIn *hwi = NULL;
+
+ while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
+ hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
+ hwo->pcm_ops->fini_out (hwo);
+ }
+
+ while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
+ hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
+ hwi->pcm_ops->fini_in (hwi);
+ }
+
+ if (s->drv) {
+ s->drv->fini (s->drv_opaque);
+ }
}
static void audio_save (QEMUFile *f, void *opaque)
{
+ (void) f;
+ (void) opaque;
}
static int audio_load (QEMUFile *f, void *opaque, int version_id)
{
- if (version_id != 1)
+ (void) f;
+ (void) opaque;
+
+ if (version_id != 1) {
return -EINVAL;
+ }
return 0;
}
-void AUD_init (void)
-{
- int i;
+void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card)
+{
+ card->audio = s;
+ card->name = qemu_strdup (name);
+ memset (&card->entries, 0, sizeof (card->entries));
+ LIST_INSERT_HEAD (&s->card_head, card, entries);
+}
+
+void AUD_remove_card (QEMUSoundCard *card)
+{
+ LIST_REMOVE (card, entries);
+ card->audio = NULL;
+ qemu_free (card->name);
+}
+
+AudioState *AUD_init (void)
+{
+ size_t i;
int done = 0;
const char *drvname;
-
- audio_state.fixed_format =
- !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
- audio_state.fixed_freq =
- audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
- audio_state.nb_hw_voices =
- audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
-
- if (audio_state.nb_hw_voices <= 0) {
- dolog ("Bogus number of voices %d, resetting to 1\n",
- audio_state.nb_hw_voices);
- }
-
- drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
+ AudioState *s = &glob_audio_state;
+
+ LIST_INIT (&s->hw_head_out);
+ LIST_INIT (&s->hw_head_in);
+ atexit (audio_atexit);
+
+ s->ts = qemu_new_timer (vm_clock, audio_timer, s);
+ if (!s->ts) {
+ dolog ("Could not create audio timer\n");
+ return NULL;
+ }
+
+ audio_process_options ("AUDIO", audio_options);
+
+ s->nb_hw_voices_out = conf.fixed_out.nb_voices;
+ s->nb_hw_voices_in = conf.fixed_in.nb_voices;
+
+ if (s->nb_hw_voices_out <= 0) {
+ dolog ("Bogus number of playback voices %d, setting to 1\n",
+ s->nb_hw_voices_out);
+ s->nb_hw_voices_out = 1;
+ }
+
+ if (s->nb_hw_voices_in <= 0) {
+ dolog ("Bogus number of capture voices %d, setting to 0\n",
+ s->nb_hw_voices_in);
+ s->nb_hw_voices_in = 0;
+ }
+
+ {
+ int def;
+ drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);
+ }
+
if (drvname) {
int found = 0;
+
for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
if (!strcmp (drvname, drvtab[i]->name)) {
- done = voice_init (drvtab[i]);
+ done = !audio_driver_init (s, drvtab[i]);
found = 1;
break;
}
}
+
if (!found) {
dolog ("Unknown audio driver `%s'\n", drvname);
- }
- }
-
- qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
- atexit (audio_atexit);
+ dolog ("Run with -audio-help to list available drivers\n");
+ }
+ }
if (!done) {
for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
- if (drvtab[i]->can_be_default)
- done = voice_init (drvtab[i]);
- }
- }
-
- audio_state.ticks_threshold = ticks_per_sec / 50;
- audio_state.freq_threshold = 100;
-
- register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
+ if (drvtab[i]->can_be_default) {
+ done = !audio_driver_init (s, drvtab[i]);
+ }
+ }
+ }
+
if (!done) {
- dolog ("Can not initialize audio subsystem\n");
- voice_init (&no_output_driver);
- }
-}
+ done = !audio_driver_init (s, &no_audio_driver);
+ if (!done) {
+ dolog ("Could not initialize audio subsystem\n");
+ }
+ else {
+ dolog ("warning: Using timer based audio emulation\n");
+ }
+ }
+
+ if (done) {
+ VMChangeStateEntry *e;
+
+ if (conf.period.hz <= 0) {
+ if (conf.period.hz < 0) {
+ dolog ("warning: Timer period is negative - %d "
+ "treating as zero\n",
+ conf.period.hz);
+ }
+ conf.period.ticks = 1;
+ }
+ else {
+ conf.period.ticks = ticks_per_sec / conf.period.hz;
+ }
+
+ e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler,
s);
+ if (!e) {
+ dolog ("warning: Could not register change state handler\n"
+ "(Audio can continue looping even after stopping the
VM)\n");
+ }
+ }
+ else {
+ qemu_del_timer (s->ts);
+ return NULL;
+ }
+
+ LIST_INIT (&s->card_head);
+ register_savevm ("audio", 0, 1, audio_save, audio_load, s);
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
+ return s;
+}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio.h
--- a/tools/ioemu/audio/audio.h Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio.h Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
* QEMU Audio subsystem header
- *
- * Copyright (c) 2003-2004 Vassili Karpov (malc)
- *
+ *
+ * Copyright (c) 2003-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -24,31 +24,85 @@
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
-#include "mixeng.h"
+#include "sys-queue.h"
+
+typedef void (*audio_callback_fn_t) (void *opaque, int avail);
typedef enum {
- AUD_FMT_U8,
- AUD_FMT_S8,
- AUD_FMT_U16,
- AUD_FMT_S16
+ AUD_FMT_U8,
+ AUD_FMT_S8,
+ AUD_FMT_U16,
+ AUD_FMT_S16
} audfmt_e;
-typedef struct SWVoice SWVoice;
+typedef struct {
+ int freq;
+ int nchannels;
+ audfmt_e fmt;
+} audsettings_t;
-SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
- int nchannels, audfmt_e fmt);
-void AUD_init (void);
-void AUD_log (const char *cap, const char *fmt, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));;
-void AUD_close (SWVoice *sw);
-int AUD_write (SWVoice *sw, void *pcm_buf, int size);
-void AUD_adjust (SWVoice *sw, int leftover);
-void AUD_reset (SWVoice *sw);
-int AUD_get_free (SWVoice *sw);
-int AUD_get_buffer_size (SWVoice *sw);
-void AUD_run (void);
-void AUD_enable (SWVoice *sw, int on);
-int AUD_calc_elapsed (SWVoice *sw);
+typedef struct AudioState AudioState;
+typedef struct SWVoiceOut SWVoiceOut;
+typedef struct SWVoiceIn SWVoiceIn;
+
+typedef struct QEMUSoundCard {
+ AudioState *audio;
+ char *name;
+ LIST_ENTRY (QEMUSoundCard) entries;
+} QEMUSoundCard;
+
+typedef struct QEMUAudioTimeStamp {
+ uint64_t old_ts;
+} QEMUAudioTimeStamp;
+
+void AUD_vlog (const char *cap, const char *fmt, va_list ap);
+void AUD_log (const char *cap, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((__format__ (__printf__, 2, 3)))
+#endif
+ ;
+
+AudioState *AUD_init (void);
+void AUD_help (void);
+void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card);
+void AUD_remove_card (QEMUSoundCard *card);
+
+SWVoiceOut *AUD_open_out (
+ QEMUSoundCard *card,
+ SWVoiceOut *sw,
+ const char *name,
+ void *callback_opaque,
+ audio_callback_fn_t callback_fn,
+ audsettings_t *settings,
+ int sw_endian
+ );
+
+void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
+int AUD_write (SWVoiceOut *sw, void *pcm_buf, int size);
+int AUD_get_buffer_size_out (SWVoiceOut *sw);
+void AUD_set_active_out (SWVoiceOut *sw, int on);
+int AUD_is_active_out (SWVoiceOut *sw);
+
+void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
+uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
+
+SWVoiceIn *AUD_open_in (
+ QEMUSoundCard *card,
+ SWVoiceIn *sw,
+ const char *name,
+ void *callback_opaque,
+ audio_callback_fn_t callback_fn,
+ audsettings_t *settings,
+ int sw_endian
+ );
+
+void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
+int AUD_read (SWVoiceIn *sw, void *pcm_buf, int size);
+void AUD_set_active_in (SWVoiceIn *sw, int on);
+int AUD_is_active_in (SWVoiceIn *sw);
+
+void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
+uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
static inline void *advance (void *p, int incr)
{
@@ -59,7 +113,21 @@ uint32_t popcount (uint32_t u);
uint32_t popcount (uint32_t u);
inline uint32_t lsbindex (uint32_t u);
+#ifdef __GNUC__
+#define audio_MIN(a, b) ( __extension__ ({ \
+ __typeof (a) ta = a; \
+ __typeof (b) tb = b; \
+ ((ta)>(tb)?(tb):(ta)); \
+}))
+
+#define audio_MAX(a, b) ( __extension__ ({ \
+ __typeof (a) ta = a; \
+ __typeof (b) tb = b; \
+ ((ta)<(tb)?(tb):(ta)); \
+}))
+#else
#define audio_MIN(a, b) ((a)>(b)?(b):(a))
#define audio_MAX(a, b) ((a)<(b)?(b):(a))
+#endif
#endif /* audio.h */
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/audio_int.h
--- a/tools/ioemu/audio/audio_int.h Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/audio_int.h Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
* QEMU Audio subsystem header
- *
- * Copyright (c) 2003-2004 Vassili Karpov (malc)
- *
+ *
+ * Copyright (c) 2003-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -24,141 +24,245 @@
#ifndef QEMU_AUDIO_INT_H
#define QEMU_AUDIO_INT_H
-#include "vl.h"
-
-struct pcm_ops;
-
-typedef struct HWVoice {
- int active;
+#ifdef CONFIG_COREAUDIO
+#define FLOAT_MIXENG
+/* #define RECIPROCAL */
+#endif
+#include "mixeng.h"
+
+struct audio_pcm_ops;
+
+typedef enum {
+ AUD_OPT_INT,
+ AUD_OPT_FMT,
+ AUD_OPT_STR,
+ AUD_OPT_BOOL
+} audio_option_tag_e;
+
+struct audio_option {
+ const char *name;
+ audio_option_tag_e tag;
+ void *valp;
+ const char *descr;
+ int *overridenp;
+ int overriden;
+};
+
+struct audio_callback {
+ void *opaque;
+ audio_callback_fn_t fn;
+};
+
+struct audio_pcm_info {
+ int bits;
+ int sign;
+ int freq;
+ int nchannels;
+ int align;
+ int shift;
+ int bytes_per_second;
+ int swap_endian;
+};
+
+typedef struct HWVoiceOut {
int enabled;
int pending_disable;
int valid;
- int freq;
+ struct audio_pcm_info info;
f_sample *clip;
- audfmt_e fmt;
- int nchannels;
-
- int align;
- int shift;
int rpos;
- int bufsize;
-
- int bytes_per_second;
+ uint64_t ts_helper;
+
st_sample_t *mix_buf;
int samples;
- int64_t old_ticks;
- int nb_voices;
- struct SWVoice **pvoice;
- struct pcm_ops *pcm_ops;
-} HWVoice;
-
-extern struct pcm_ops no_pcm_ops;
-extern struct audio_output_driver no_output_driver;
-
-extern struct pcm_ops oss_pcm_ops;
-extern struct audio_output_driver oss_output_driver;
-
-extern struct pcm_ops sdl_pcm_ops;
-extern struct audio_output_driver sdl_output_driver;
-
-extern struct pcm_ops wav_pcm_ops;
-extern struct audio_output_driver wav_output_driver;
-
-extern struct pcm_ops fmod_pcm_ops;
-extern struct audio_output_driver fmod_output_driver;
-
-struct audio_output_driver {
- const char *name;
- void *(*init) (void);
- void (*fini) (void *);
- struct pcm_ops *pcm_ops;
- int can_be_default;
- int max_voices;
- int voice_size;
-};
-
-typedef struct AudioState {
- int fixed_format;
- int fixed_freq;
- int fixed_channels;
- int fixed_fmt;
- int nb_hw_voices;
- int voice_size;
- int64_t ticks_threshold;
- int freq_threshold;
- void *opaque;
- struct audio_output_driver *drv;
-} AudioState;
-extern AudioState audio_state;
-
-struct SWVoice {
- int freq;
- audfmt_e fmt;
- int nchannels;
-
- int shift;
- int align;
+ LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
+ struct audio_pcm_ops *pcm_ops;
+ LIST_ENTRY (HWVoiceOut) entries;
+} HWVoiceOut;
+
+typedef struct HWVoiceIn {
+ int enabled;
+ struct audio_pcm_info info;
t_sample *conv;
- int left;
- int pos;
- int bytes_per_second;
+ int wpos;
+ int total_samples_captured;
+ uint64_t ts_helper;
+
+ st_sample_t *conv_buf;
+
+ int samples;
+ LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
+ struct audio_pcm_ops *pcm_ops;
+ LIST_ENTRY (HWVoiceIn) entries;
+} HWVoiceIn;
+
+struct SWVoiceOut {
+ struct audio_pcm_info info;
+ t_sample *conv;
int64_t ratio;
st_sample_t *buf;
void *rate;
-
- int wpos;
- int live;
+ int total_hw_samples_mixed;
int active;
- int64_t old_ticks;
- HWVoice *hw;
+ int empty;
+ HWVoiceOut *hw;
char *name;
-};
-
-struct pcm_ops {
- int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
- void (*fini) (HWVoice *hw);
- void (*run) (HWVoice *hw);
- int (*write) (SWVoice *sw, void *buf, int size);
- int (*ctl) (HWVoice *hw, int cmd, ...);
-};
-
-void pcm_sw_free_resources (SWVoice *sw);
-int pcm_sw_alloc_resources (SWVoice *sw);
-void pcm_sw_fini (SWVoice *sw);
-int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
- int nchannels, audfmt_e fmt);
-
-void pcm_hw_clear (HWVoice *hw, void *buf, int len);
-HWVoice * pcm_hw_find_any (HWVoice *hw);
-HWVoice * pcm_hw_find_any_active (HWVoice *hw);
-HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
-HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
- int nchannels, audfmt_e fmt);
-HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
-int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
-int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
-SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
-
-void pcm_hw_free_resources (HWVoice *hw);
-int pcm_hw_alloc_resources (HWVoice *hw);
-void pcm_hw_fini (HWVoice *hw);
-void pcm_hw_gc (HWVoice *hw);
-int pcm_hw_get_live (HWVoice *hw);
-int pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
-void pcm_hw_dec_live (HWVoice *hw, int decr);
-int pcm_hw_write (SWVoice *sw, void *buf, int len);
-
-int audio_get_conf_int (const char *key, int defval);
-const char *audio_get_conf_str (const char *key, const char *defval);
-
-struct audio_output_driver;
+ volume_t vol;
+ struct audio_callback callback;
+ LIST_ENTRY (SWVoiceOut) entries;
+};
+
+struct SWVoiceIn {
+ int active;
+ struct audio_pcm_info info;
+ int64_t ratio;
+ void *rate;
+ int total_hw_samples_acquired;
+ st_sample_t *buf;
+ f_sample *clip;
+ HWVoiceIn *hw;
+ char *name;
+ volume_t vol;
+ struct audio_callback callback;
+ LIST_ENTRY (SWVoiceIn) entries;
+};
+
+struct audio_driver {
+ const char *name;
+ const char *descr;
+ struct audio_option *options;
+ void *(*init) (void);
+ void (*fini) (void *);
+ struct audio_pcm_ops *pcm_ops;
+ int can_be_default;
+ int max_voices_out;
+ int max_voices_in;
+ int voice_size_out;
+ int voice_size_in;
+};
+
+struct audio_pcm_ops {
+ int (*init_out)(HWVoiceOut *hw, audsettings_t *as);
+ void (*fini_out)(HWVoiceOut *hw);
+ int (*run_out) (HWVoiceOut *hw);
+ int (*write) (SWVoiceOut *sw, void *buf, int size);
+ int (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
+
+ int (*init_in) (HWVoiceIn *hw, audsettings_t *as);
+ void (*fini_in) (HWVoiceIn *hw);
+ int (*run_in) (HWVoiceIn *hw);
+ int (*read) (SWVoiceIn *sw, void *buf, int size);
+ int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
+};
+
+struct AudioState {
+ struct audio_driver *drv;
+ void *drv_opaque;
+
+ QEMUTimer *ts;
+ LIST_HEAD (card_head, QEMUSoundCard) card_head;
+ LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
+ LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
+ int nb_hw_voices_out;
+ int nb_hw_voices_in;
+};
+
+extern struct audio_driver no_audio_driver;
+extern struct audio_driver oss_audio_driver;
+extern struct audio_driver sdl_audio_driver;
+extern struct audio_driver wav_audio_driver;
+extern struct audio_driver fmod_audio_driver;
+extern struct audio_driver alsa_audio_driver;
+extern struct audio_driver coreaudio_audio_driver;
+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_info_clear_buf (struct audio_pcm_info *info, void *buf, int
len);
+
+int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
+int audio_pcm_hw_get_live_in (HWVoiceIn *hw);
+
+int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len);
+int audio_pcm_hw_get_live_out (HWVoiceOut *hw);
+int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live);
+
+int audio_bug (const char *funcname, int cond);
+void *audio_calloc (const char *funcname, int nmemb, size_t size);
#define VOICE_ENABLE 1
#define VOICE_DISABLE 2
+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__
+#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2)))
+#define INIT_FIELD(f) . f
+#define GCC_FMT_ATTR(n, m) __attribute__ ((__format__ (__printf__, n, m)))
+#else
+#define GCC_ATTR /**/
+#define INIT_FIELD(f) /**/
+#define GCC_FMT_ATTR(n, m)
+#endif
+
+static void GCC_ATTR dolog (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ AUD_vlog (AUDIO_CAP, fmt, ap);
+ va_end (ap);
+}
+
+#ifdef DEBUG
+static void GCC_ATTR ldebug (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ AUD_vlog (AUDIO_CAP, fmt, ap);
+ va_end (ap);
+}
+#else
+#if defined NDEBUG && defined __GNUC__
+#define ldebug(...)
+#elif defined NDEBUG && defined _MSC_VER
+#define ldebug __noop
+#else
+static void GCC_ATTR ldebug (const char *fmt, ...)
+{
+ (void) fmt;
+}
+#endif
+#endif
+
+#undef GCC_ATTR
+
+#define AUDIO_STRINGIFY_(n) #n
+#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
+
+#if defined _MSC_VER || defined __GNUC__
+#define AUDIO_FUNC __FUNCTION__
+#else
+#define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__)
+#endif
+
#endif /* audio_int.h */
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng.c
--- a/tools/ioemu/audio/mixeng.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,7 +1,7 @@
/*
* QEMU Mixing engine
*
- * Copyright (c) 2004 Vassili Karpov (malc)
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
* Copyright (c) 1998 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,87 +23,174 @@
* THE SOFTWARE.
*/
#include "vl.h"
-//#define DEBUG_FP
-#include "audio/mixeng.h"
-
+
+#define AUDIO_CAP "mixeng"
+#include "audio_int.h"
+
+#define NOVOL
+
+/* 8 bit */
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+
+/* Signed 8 bit */
#define IN_T int8_t
-#define IN_MIN CHAR_MIN
-#define IN_MAX CHAR_MAX
+#define IN_MIN SCHAR_MIN
+#define IN_MAX SCHAR_MAX
#define SIGNED
+#define SHIFT 8
#include "mixeng_template.h"
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
-
+#undef SHIFT
+
+/* Unsigned 8 bit */
#define IN_T uint8_t
#define IN_MIN 0
#define IN_MAX UCHAR_MAX
-#include "mixeng_template.h"
-#undef IN_MAX
-#undef IN_MIN
-#undef IN_T
-
+#define SHIFT 8
+#include "mixeng_template.h"
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+
+/* Signed 16 bit */
#define IN_T int16_t
#define IN_MIN SHRT_MIN
#define IN_MAX SHRT_MAX
#define SIGNED
-#include "mixeng_template.h"
+#define SHIFT 16
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap16 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
+#undef SHIFT
#define IN_T uint16_t
#define IN_MIN 0
#define IN_MAX USHRT_MAX
-#include "mixeng_template.h"
-#undef IN_MAX
-#undef IN_MIN
-#undef IN_T
-
-t_sample *mixeng_conv[2][2][2] = {
- {
- {
- conv_uint8_t_to_mono,
- conv_uint16_t_to_mono
- },
- {
- conv_int8_t_to_mono,
- conv_int16_t_to_mono
+#define SHIFT 16
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap16 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+t_sample *mixeng_conv[2][2][2][2] = {
+ {
+ {
+ {
+ conv_natural_uint8_t_to_mono,
+ conv_natural_uint16_t_to_mono
+ },
+ {
+ conv_natural_uint8_t_to_mono,
+ conv_swap_uint16_t_to_mono
+ }
+ },
+ {
+ {
+ conv_natural_int8_t_to_mono,
+ conv_natural_int16_t_to_mono
+ },
+ {
+ conv_natural_int8_t_to_mono,
+ conv_swap_int16_t_to_mono
+ }
}
},
{
{
- conv_uint8_t_to_stereo,
- conv_uint16_t_to_stereo
- },
- {
- conv_int8_t_to_stereo,
- conv_int16_t_to_stereo
- }
- }
-};
-
-f_sample *mixeng_clip[2][2][2] = {
- {
- {
- clip_uint8_t_from_mono,
- clip_uint16_t_from_mono
- },
- {
- clip_int8_t_from_mono,
- clip_int16_t_from_mono
+ {
+ conv_natural_uint8_t_to_stereo,
+ conv_natural_uint16_t_to_stereo
+ },
+ {
+ conv_natural_uint8_t_to_stereo,
+ conv_swap_uint16_t_to_stereo
+ }
+ },
+ {
+ {
+ conv_natural_int8_t_to_stereo,
+ conv_natural_int16_t_to_stereo
+ },
+ {
+ conv_natural_int8_t_to_stereo,
+ conv_swap_int16_t_to_stereo
+ }
+ }
+ }
+};
+
+f_sample *mixeng_clip[2][2][2][2] = {
+ {
+ {
+ {
+ clip_natural_uint8_t_from_mono,
+ clip_natural_uint16_t_from_mono
+ },
+ {
+ clip_natural_uint8_t_from_mono,
+ clip_swap_uint16_t_from_mono
+ }
+ },
+ {
+ {
+ clip_natural_int8_t_from_mono,
+ clip_natural_int16_t_from_mono
+ },
+ {
+ clip_natural_int8_t_from_mono,
+ clip_swap_int16_t_from_mono
+ }
}
},
{
{
- clip_uint8_t_from_stereo,
- clip_uint16_t_from_stereo
- },
- {
- clip_int8_t_from_stereo,
- clip_int16_t_from_stereo
+ {
+ clip_natural_uint8_t_from_stereo,
+ clip_natural_uint16_t_from_stereo
+ },
+ {
+ clip_natural_uint8_t_from_stereo,
+ clip_swap_uint16_t_from_stereo
+ }
+ },
+ {
+ {
+ clip_natural_int8_t_from_stereo,
+ clip_natural_int16_t_from_stereo
+ },
+ {
+ clip_natural_int8_t_from_stereo,
+ clip_swap_int16_t_from_stereo
+ }
}
}
};
@@ -116,9 +203,9 @@ f_sample *mixeng_clip[2][2][2] = {
* Contributors with a more efficient algorithm.]
*
* This source code is freely redistributable and may be used for
- * any purpose. This copyright notice must be maintained.
- * Lance Norskog And Sundry Contributors are not responsible for
- * the consequences of using this software.
+ * any purpose. This copyright notice must be maintained.
+ * Lance Norskog And Sundry Contributors are not responsible for
+ * the consequences of using this software.
*/
/*
@@ -141,36 +228,29 @@ f_sample *mixeng_clip[2][2][2] = {
*/
/* Private data */
-typedef struct ratestuff {
+struct rate {
uint64_t opos;
uint64_t opos_inc;
uint32_t ipos; /* position in the input stream (integer) */
st_sample_t ilast; /* last sample in the input stream */
-} *rate_t;
+};
/*
* Prepare processing.
*/
void *st_rate_start (int inrate, int outrate)
{
- rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
+ struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
if (!rate) {
- exit (EXIT_FAILURE);
- }
-
- if (inrate == outrate) {
- // exit (EXIT_FAILURE);
- }
-
- if (inrate >= 65535 || outrate >= 65535) {
- // exit (EXIT_FAILURE);
+ dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
+ return NULL;
}
rate->opos = 0;
/* increment */
- rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
+ rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
rate->ipos = 0;
rate->ilast.l = 0;
@@ -178,78 +258,20 @@ void *st_rate_start (int inrate, int out
return rate;
}
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
- int *isamp, int *osamp)
-{
- rate_t rate = (rate_t) opaque;
- st_sample_t *istart, *iend;
- st_sample_t *ostart, *oend;
- st_sample_t ilast, icur, out;
- int64_t t;
-
- ilast = rate->ilast;
-
- istart = ibuf;
- iend = ibuf + *isamp;
-
- ostart = obuf;
- oend = obuf + *osamp;
-
- if (rate->opos_inc == 1ULL << 32) {
- int i, n = *isamp > *osamp ? *osamp : *isamp;
- for (i = 0; i < n; i++) {
- obuf[i].l += ibuf[i].r;
- obuf[i].r += ibuf[i].r;
- }
- *isamp = n;
- *osamp = n;
- return;
- }
-
- while (obuf < oend) {
-
- /* Safety catch to make sure we have input samples. */
- if (ibuf >= iend)
- break;
-
- /* read as many input samples so that ipos > opos */
-
- while (rate->ipos <= (rate->opos >> 32)) {
- ilast = *ibuf++;
- rate->ipos++;
- /* See if we finished the input buffer yet */
- if (ibuf >= iend) goto the_end;
- }
-
- icur = *ibuf;
-
- /* interpolate */
- t = rate->opos & 0xffffffff;
- out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
- out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
-
- /* output sample & increment position */
-#if 0
- *obuf++ = out;
-#else
- obuf->l += out.l;
- obuf->r += out.r;
- obuf += 1;
-#endif
- rate->opos += rate->opos_inc;
- }
-
-the_end:
- *isamp = ibuf - istart;
- *osamp = obuf - ostart;
- rate->ilast = ilast;
-}
+#define NAME st_rate_flow_mix
+#define OP(a, b) a += b
+#include "rate_template.h"
+
+#define NAME st_rate_flow
+#define OP(a, b) a = b
+#include "rate_template.h"
void st_rate_stop (void *opaque)
{
qemu_free (opaque);
}
+
+void mixeng_clear (st_sample_t *buf, int len)
+{
+ memset (buf, 0, len * sizeof (st_sample_t));
+}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng.h
--- a/tools/ioemu/audio/mixeng.h Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng.h Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
* QEMU Mixing engine header
- *
- * Copyright (c) 2004 Vassili Karpov (malc)
- *
+ *
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -24,16 +24,28 @@
#ifndef QEMU_MIXENG_H
#define QEMU_MIXENG_H
-typedef void (t_sample) (void *dst, const void *src, int samples);
-typedef void (f_sample) (void *dst, const void *src, int samples);
+#ifdef FLOAT_MIXENG
+typedef float real_t;
+typedef struct { int mute; real_t r; real_t l; } volume_t;
+typedef struct { real_t l; real_t r; } st_sample_t;
+#else
+typedef struct { int mute; int64_t r; int64_t l; } volume_t;
typedef struct { int64_t l; int64_t r; } st_sample_t;
+#endif
-extern t_sample *mixeng_conv[2][2][2];
-extern f_sample *mixeng_clip[2][2][2];
+typedef void (t_sample) (st_sample_t *dst, const void *src,
+ int samples, volume_t *vol);
+typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
+
+extern t_sample *mixeng_conv[2][2][2][2];
+extern f_sample *mixeng_clip[2][2][2][2];
void *st_rate_start (int inrate, int outrate);
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp);
+void st_rate_flow_mix (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
+ int *isamp, int *osamp);
void st_rate_stop (void *opaque);
+void mixeng_clear (st_sample_t *buf, int len);
#endif /* mixeng.h */
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/mixeng_template.h
--- a/tools/ioemu/audio/mixeng_template.h Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/mixeng_template.h Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
* QEMU Mixing engine
- *
- * Copyright (c) 2004 Vassili Karpov (malc)
- *
+ *
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -27,85 +27,151 @@
* dec++'ified by Dscho
*/
-#ifdef SIGNED
-#define HALFT IN_MAX
-#define HALF IN_MAX
-#else
-#define HALFT ((IN_MAX)>>1)
-#define HALF HALFT
+#ifndef SIGNED
+#define HALF (IN_MAX >> 1)
#endif
-static int64_t inline glue(conv_,IN_T) (IN_T v)
+#ifdef NOVOL
+#define VOL(a, b) a
+#else
+#ifdef FLOAT_MIXENG
+#define VOL(a, b) ((a) * (b))
+#else
+#define VOL(a, b) ((a) * (b)) >> 32
+#endif
+#endif
+
+#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
+
+#ifdef FLOAT_MIXENG
+static real_t inline glue (conv_, ET) (IN_T v)
{
+ IN_T nv = ENDIAN_CONVERT (v);
+
+#ifdef RECIPROCAL
#ifdef SIGNED
- return (INT_MAX*(int64_t)v)/HALF;
+ return nv * (1.f / (real_t) (IN_MAX - IN_MIN));
#else
- return (INT_MAX*((int64_t)v-HALFT))/HALF;
+ return (nv - HALF) * (1.f / (real_t) IN_MAX);
+#endif
+#else /* !RECIPROCAL */
+#ifdef SIGNED
+ return nv / (real_t) (IN_MAX - IN_MIN);
+#else
+ return (nv - HALF) / (real_t) IN_MAX;
+#endif
#endif
}
-static IN_T inline glue(clip_,IN_T) (int64_t v)
+static IN_T inline glue (clip_, ET) (real_t v)
{
- if (v >= INT_MAX)
+ if (v >= 0.5) {
return IN_MAX;
- else if (v < -INT_MAX)
+ }
+ else if (v < -0.5) {
return IN_MIN;
+ }
#ifdef SIGNED
- return (IN_T) (v*HALF/INT_MAX);
+ return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN)));
#else
- return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX;
+ return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
#endif
}
-static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src,
- int samples)
+#else /* !FLOAT_MIXENG */
+
+static inline int64_t glue (conv_, ET) (IN_T v)
{
- st_sample_t *out = (st_sample_t *) dst;
+ IN_T nv = ENDIAN_CONVERT (v);
+#ifdef SIGNED
+ return ((int64_t) nv) << (32 - SHIFT);
+#else
+ return ((int64_t) nv - HALF) << (32 - SHIFT);
+#endif
+}
+
+static inline IN_T glue (clip_, ET) (int64_t v)
+{
+ if (v >= 0x7f000000) {
+ return IN_MAX;
+ }
+ else if (v < -2147483648LL) {
+ return IN_MIN;
+ }
+
+#ifdef SIGNED
+ return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT)));
+#else
+ return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF));
+#endif
+}
+#endif
+
+static void glue (glue (conv_, ET), _to_stereo)
+ (st_sample_t *dst, const void *src, int samples, volume_t *vol)
+{
+ st_sample_t *out = dst;
IN_T *in = (IN_T *) src;
+#ifndef NOVOL
+ if (vol->mute) {
+ mixeng_clear (dst, samples);
+ return;
+ }
+#else
+ (void) vol;
+#endif
while (samples--) {
- out->l = glue(conv_,IN_T) (*in++);
- out->r = glue(conv_,IN_T) (*in++);
+ out->l = VOL (glue (conv_, ET) (*in++), vol->l);
+ out->r = VOL (glue (conv_, ET) (*in++), vol->r);
out += 1;
}
}
-static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src,
- int samples)
+static void glue (glue (conv_, ET), _to_mono)
+ (st_sample_t *dst, const void *src, int samples, volume_t *vol)
{
- st_sample_t *out = (st_sample_t *) dst;
+ st_sample_t *out = dst;
IN_T *in = (IN_T *) src;
+#ifndef NOVOL
+ if (vol->mute) {
+ mixeng_clear (dst, samples);
+ return;
+ }
+#else
+ (void) vol;
+#endif
while (samples--) {
- out->l = glue(conv_,IN_T) (in[0]);
+ out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
out->r = out->l;
out += 1;
in += 1;
}
}
-static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src,
- int samples)
+static void glue (glue (clip_, ET), _from_stereo)
+ (void *dst, const st_sample_t *src, int samples)
{
- st_sample_t *in = (st_sample_t *) src;
+ const st_sample_t *in = src;
IN_T *out = (IN_T *) dst;
while (samples--) {
- *out++ = glue(clip_,IN_T) (in->l);
- *out++ = glue(clip_,IN_T) (in->r);
+ *out++ = glue (clip_, ET) (in->l);
+ *out++ = glue (clip_, ET) (in->r);
in += 1;
}
}
-static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src,
- int samples)
+static void glue (glue (clip_, ET), _from_mono)
+ (void *dst, const st_sample_t *src, int samples)
{
- st_sample_t *in = (st_sample_t *) src;
+ const st_sample_t *in = src;
IN_T *out = (IN_T *) dst;
while (samples--) {
- *out++ = glue(clip_,IN_T) (in->l + in->r);
+ *out++ = glue (clip_, ET) (in->l + in->r);
in += 1;
}
}
+#undef ET
#undef HALF
-#undef HALFT
-
+#undef VOL
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/noaudio.c
--- a/tools/ioemu/audio/noaudio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/noaudio.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
- * QEMU NULL audio output driver
- *
- * Copyright (c) 2004 Vassili Karpov (malc)
- *
+ * QEMU Timer based audio emulation
+ *
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -23,77 +23,108 @@
*/
#include "vl.h"
-#include "audio/audio_int.h"
+#define AUDIO_CAP "noaudio"
+#include "audio_int.h"
-typedef struct NoVoice {
- HWVoice hw;
+typedef struct NoVoiceOut {
+ HWVoiceOut hw;
int64_t old_ticks;
-} NoVoice;
+} NoVoiceOut;
-#define dolog(...) AUD_log ("noaudio", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
+typedef struct NoVoiceIn {
+ HWVoiceIn hw;
+ int64_t old_ticks;
+} NoVoiceIn;
-static void no_hw_run (HWVoice *hw)
+static int no_run_out (HWVoiceOut *hw)
{
- NoVoice *no = (NoVoice *) hw;
- int rpos, live, decr, samples;
- st_sample_t *src;
+ 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->bytes_per_second) / ticks_per_sec;
+ int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
- if (bytes > INT_MAX)
- samples = INT_MAX >> hw->shift;
- else
- samples = bytes >> hw->shift;
+ if (bytes > INT_MAX) {
+ samples = INT_MAX >> hw->info.shift;
+ }
+ else {
+ samples = bytes >> hw->info.shift;
+ }
- live = pcm_hw_get_live (hw);
- if (live <= 0)
- return;
+ live = audio_pcm_hw_get_live_out (&no->hw);
+ if (!live) {
+ return 0;
+ }
no->old_ticks = now;
decr = audio_MIN (live, samples);
- samples = decr;
- rpos = hw->rpos;
- while (samples) {
- int left_till_end_samples = hw->samples - rpos;
- int convert_samples = audio_MIN (samples, left_till_end_samples);
-
- src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
- memset (src, 0, convert_samples * sizeof (st_sample_t));
-
- rpos = (rpos + convert_samples) % hw->samples;
- samples -= convert_samples;
- }
-
- pcm_hw_dec_live (hw, decr);
- hw->rpos = rpos;
+ hw->rpos = (hw->rpos + decr) % hw->samples;
+ return decr;
}
-static int no_hw_write (SWVoice *sw, void *buf, int len)
+static int no_write (SWVoiceOut *sw, void *buf, int len)
{
- return pcm_hw_write (sw, buf, len);
+ return audio_pcm_sw_write (sw, buf, len);
}
-static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
{
- hw->freq = freq;
- hw->nchannels = nchannels;
- hw->fmt = fmt;
- hw->bufsize = 4096;
+ audio_pcm_init_info (&hw->info, as, 0);
+ hw->samples = 1024;
return 0;
}
-static void no_hw_fini (HWVoice *hw)
+static void no_fini_out (HWVoiceOut *hw)
{
(void) hw;
}
-static int no_hw_ctl (HWVoice *hw, int cmd, ...)
+static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
+{
+ (void) hw;
+ (void) cmd;
+ return 0;
+}
+
+static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
+{
+ audio_pcm_init_info (&hw->info, as, 0);
+ hw->samples = 1024;
+ return 0;
+}
+
+static void no_fini_in (HWVoiceIn *hw)
+{
+ (void) 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;
+
+ bytes = audio_MIN (bytes, INT_MAX);
+ samples = bytes >> hw->info.shift;
+ samples = audio_MIN (samples, dead);
+
+ return samples;
+}
+
+static int no_read (SWVoiceIn *sw, void *buf, int size)
+{
+ int samples = size >> sw->info.shift;
+ int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
+ int to_clear = audio_MIN (samples, total);
+ audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
+ return to_clear;
+}
+
+static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
@@ -107,22 +138,33 @@ static void *no_audio_init (void)
static void no_audio_fini (void *opaque)
{
+ (void) opaque;
}
-struct pcm_ops no_pcm_ops = {
- no_hw_init,
- no_hw_fini,
- no_hw_run,
- no_hw_write,
- no_hw_ctl
+static struct audio_pcm_ops no_pcm_ops = {
+ no_init_out,
+ no_fini_out,
+ no_run_out,
+ no_write,
+ no_ctl_out,
+
+ no_init_in,
+ no_fini_in,
+ no_run_in,
+ no_read,
+ no_ctl_in
};
-struct audio_output_driver no_output_driver = {
- "none",
- no_audio_init,
- no_audio_fini,
- &no_pcm_ops,
- 1,
- 1,
- sizeof (NoVoice)
+struct audio_driver no_audio_driver = {
+ INIT_FIELD (name = ) "none",
+ INIT_FIELD (descr = ) "Timer based audio emulation",
+ INIT_FIELD (options = ) NULL,
+ INIT_FIELD (init = ) no_audio_init,
+ INIT_FIELD (fini = ) no_audio_fini,
+ INIT_FIELD (pcm_ops = ) &no_pcm_ops,
+ INIT_FIELD (can_be_default = ) 1,
+ INIT_FIELD (max_voices_out = ) INT_MAX,
+ INIT_FIELD (max_voices_in = ) INT_MAX,
+ INIT_FIELD (voice_size_out = ) sizeof (NoVoiceOut),
+ INIT_FIELD (voice_size_in = ) sizeof (NoVoiceIn)
};
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/ossaudio.c
--- a/tools/ioemu/audio/ossaudio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/ossaudio.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
- * QEMU OSS audio output driver
- *
- * Copyright (c) 2003-2004 Vassili Karpov (malc)
- *
+ * QEMU OSS audio driver
+ *
+ * Copyright (c) 2003-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -25,45 +25,42 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
-#include <assert.h>
#include "vl.h"
-#include "audio/audio_int.h"
-
-typedef struct OSSVoice {
- HWVoice hw;
+#define AUDIO_CAP "oss"
+#include "audio_int.h"
+
+typedef struct OSSVoiceOut {
+ HWVoiceOut hw;
void *pcm_buf;
int fd;
int nfrags;
int fragsize;
int mmapped;
int old_optr;
-} OSSVoice;
-
-#define dolog(...) AUD_log ("oss", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
-
-#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
-#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
-#define QC_OSS_MMAP "QEMU_OSS_MMAP"
-#define QC_OSS_DEV "QEMU_OSS_DEV"
-
-#define errstr() strerror (errno)
+} OSSVoiceOut;
+
+typedef struct OSSVoiceIn {
+ HWVoiceIn hw;
+ void *pcm_buf;
+ int fd;
+ int nfrags;
+ int fragsize;
+ int old_optr;
+} OSSVoiceIn;
static struct {
int try_mmap;
int nfrags;
int fragsize;
- const char *dspname;
+ const char *devpath_out;
+ const char *devpath_in;
} conf = {
.try_mmap = 0,
.nfrags = 4,
.fragsize = 4096,
- .dspname = "/dev/dsp"
+ .devpath_out = "/dev/dsp",
+ .devpath_in = "/dev/dsp"
};
struct oss_params {
@@ -74,65 +71,141 @@ struct oss_params {
int fragsize;
};
-static int oss_hw_write (SWVoice *sw, void *buf, int len)
-{
- return pcm_hw_write (sw, buf, len);
-}
-
-static int AUD_to_ossfmt (audfmt_e fmt)
+static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ AUD_vlog (AUDIO_CAP, fmt, ap);
+ va_end (ap);
+
+ AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
+}
+
+static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
+ int err,
+ const char *typ,
+ const char *fmt,
+ ...
+ )
+{
+ va_list ap;
+
+ AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
+
+ va_start (ap, fmt);
+ AUD_vlog (AUDIO_CAP, fmt, ap);
+ va_end (ap);
+
+ AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
+}
+
+static void oss_anal_close (int *fdp)
+{
+ int err = close (*fdp);
+ if (err) {
+ oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
+ }
+ *fdp = -1;
+}
+
+static int oss_write (SWVoiceOut *sw, void *buf, int len)
+{
+ return audio_pcm_sw_write (sw, buf, len);
+}
+
+static int aud_to_ossfmt (audfmt_e fmt)
{
switch (fmt) {
- case AUD_FMT_S8: return AFMT_S8;
- case AUD_FMT_U8: return AFMT_U8;
- case AUD_FMT_S16: return AFMT_S16_LE;
- case AUD_FMT_U16: return AFMT_U16_LE;
+ case AUD_FMT_S8:
+ return AFMT_S8;
+
+ case AUD_FMT_U8:
+ return AFMT_U8;
+
+ case AUD_FMT_S16:
+ return AFMT_S16_LE;
+
+ case AUD_FMT_U16:
+ return AFMT_U16_LE;
+
default:
- dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
- exit (EXIT_FAILURE);
- }
-}
-
-static int oss_to_audfmt (int fmt)
-{
- switch (fmt) {
- case AFMT_S8: return AUD_FMT_S8;
- case AFMT_U8: return AUD_FMT_U8;
- case AFMT_S16_LE: return AUD_FMT_S16;
- case AFMT_U16_LE: return AUD_FMT_U16;
+ dolog ("Internal logic error: Bad audio format %d\n", fmt);
+#ifdef DEBUG_AUDIO
+ abort ();
+#endif
+ return AFMT_U8;
+ }
+}
+
+static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
+{
+ switch (ossfmt) {
+ case AFMT_S8:
+ *endianness =0;
+ *fmt = AUD_FMT_S8;
+ break;
+
+ case AFMT_U8:
+ *endianness = 0;
+ *fmt = AUD_FMT_U8;
+ break;
+
+ case AFMT_S16_LE:
+ *endianness = 0;
+ *fmt = AUD_FMT_S16;
+ break;
+
+ case AFMT_U16_LE:
+ *endianness = 0;
+ *fmt = AUD_FMT_U16;
+ break;
+
+ case AFMT_S16_BE:
+ *endianness = 1;
+ *fmt = AUD_FMT_S16;
+ break;
+
+ case AFMT_U16_BE:
+ *endianness = 1;
+ *fmt = AUD_FMT_U16;
+ break;
+
default:
- dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
- "Aborting\n",
- fmt);
- exit (EXIT_FAILURE);
- }
-}
-
-#ifdef DEBUG_PCM
-static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
+ dolog ("Unrecognized audio format %d\n", ossfmt);
+ return -1;
+ }
+
+ return 0;
+}
+
+#if defined DEBUG_MISMATCHES || defined DEBUG
+static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
{
dolog ("parameter | requested value | obtained value\n");
dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
- dolog ("channels | %10d | %10d\n", req->nchannels,
obt->nchannels);
+ dolog ("channels | %10d | %10d\n",
+ req->nchannels, obt->nchannels);
dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags);
- dolog ("fragsize | %10d | %10d\n", req->fragsize, obt->fragsize);
+ dolog ("fragsize | %10d | %10d\n",
+ req->fragsize, obt->fragsize);
}
#endif
-static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
+static int oss_open (int in, struct oss_params *req,
+ struct oss_params *obt, int *pfd)
{
int fd;
int mmmmssss;
audio_buf_info abinfo;
int fmt, freq, nchannels;
- const char *dspname = conf.dspname;
-
- fd = open (dspname, O_RDWR | O_NONBLOCK);
+ const char *dspname = in ? conf.devpath_in : conf.devpath_out;
+ const char *typ = in ? "ADC" : "DAC";
+
+ fd = open (dspname, (in ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
if (-1 == fd) {
- dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
- "Reason:%s\n",
- dspname,
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
return -1;
}
@@ -141,52 +214,35 @@ static int oss_open (struct oss_params *
fmt = req->fmt;
if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to set sample size\n"
- "Reason: %s\n",
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to set number of channels\n"
- "Reason: %s\n",
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
+ req->nchannels);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to set frequency\n"
- "Reason: %s\n",
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to set non-blocking mode\n"
- "Reason: %s\n",
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
goto err;
}
mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to set buffer length (%d, %d)\n"
- "Reason:%s\n",
- conf.nfrags, conf.fragsize,
- errstr ());
+ oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
+ req->nfrags, req->fragsize);
goto err;
}
- if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
- dolog ("Could not initialize audio hardware\n"
- "Failed to get buffer length\n"
- "Reason:%s\n",
- errstr ());
+ if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo))
{
+ oss_logerr2 (errno, typ, "Failed to get buffer length\n");
goto err;
}
@@ -197,75 +253,87 @@ static int oss_open (struct oss_params *
obt->fragsize = abinfo.fragsize;
*pfd = fd;
+#ifdef DEBUG_MISMATCHES
if ((req->fmt != obt->fmt) ||
(req->nchannels != obt->nchannels) ||
(req->freq != obt->freq) ||
(req->fragsize != obt->fragsize) ||
(req->nfrags != obt->nfrags)) {
-#ifdef DEBUG_PCM
dolog ("Audio parameters mismatch\n");
- oss_dump_pcm_info (req, obt);
+ oss_dump_info (req, obt);
+ }
#endif
- }
-
-#ifdef DEBUG_PCM
- oss_dump_pcm_info (req, obt);
+
+#ifdef DEBUG
+ oss_dump_info (req, obt);
#endif
return 0;
-err:
- close (fd);
+ err:
+ oss_anal_close (&fd);
return -1;
}
-static void oss_hw_run (HWVoice *hw)
-{
- OSSVoice *oss = (OSSVoice *) hw;
+static int oss_run_out (HWVoiceOut *hw)
+{
+ OSSVoiceOut *oss = (OSSVoiceOut *) hw;
int err, rpos, live, decr;
int samples;
uint8_t *dst;
st_sample_t *src;
struct audio_buf_info abinfo;
struct count_info cntinfo;
-
- live = pcm_hw_get_live (hw);
- if (live <= 0)
- return;
+ int bufsize;
+
+ live = audio_pcm_hw_get_live_out (hw);
+ if (!live) {
+ return 0;
+ }
+
+ bufsize = hw->samples << hw->info.shift;
if (oss->mmapped) {
int bytes;
err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
if (err < 0) {
- dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
- return;
+ oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
+ return 0;
}
if (cntinfo.ptr == oss->old_optr) {
- if (abs (hw->samples - live) < 64)
- dolog ("overrun\n");
- return;
+ if (abs (hw->samples - live) < 64) {
+ dolog ("warning: Overrun\n");
+ }
+ return 0;
}
if (cntinfo.ptr > oss->old_optr) {
bytes = cntinfo.ptr - oss->old_optr;
}
else {
- bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
- }
-
- decr = audio_MIN (bytes >> hw->shift, live);
+ bytes = bufsize + cntinfo.ptr - oss->old_optr;
+ }
+
+ decr = audio_MIN (bytes >> hw->info.shift, live);
}
else {
err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
if (err < 0) {
- dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
- return;
- }
-
- decr = audio_MIN (abinfo.bytes >> hw->shift, live);
- if (decr <= 0)
- return;
+ oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
+ return 0;
+ }
+
+ if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
+ ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
+ abinfo.bytes, bufsize);
+ return 0;
+ }
+
+ decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
+ if (!decr) {
+ return 0;
+ }
}
samples = decr;
@@ -274,33 +342,41 @@ static void oss_hw_run (HWVoice *hw)
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
- src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
- dst = advance (oss->pcm_buf, rpos << hw->shift);
+ src = hw->mix_buf + rpos;
+ dst = advance (oss->pcm_buf, rpos << hw->info.shift);
hw->clip (dst, src, convert_samples);
if (!oss->mmapped) {
int written;
- written = write (oss->fd, dst, convert_samples << hw->shift);
+ written = write (oss->fd, dst, convert_samples << hw->info.shift);
/* XXX: follow errno recommendations ? */
if (written == -1) {
- dolog ("Failed to write audio\nReason: %s\n", errstr ());
+ oss_logerr (
+ errno,
+ "Failed to write %d bytes of audio data from %p\n",
+ convert_samples << hw->info.shift,
+ dst
+ );
continue;
}
- if (written != convert_samples << hw->shift) {
- int wsamples = written >> hw->shift;
- int wbytes = wsamples << hw->shift;
+ if (written != convert_samples << hw->info.shift) {
+ int wsamples = written >> hw->info.shift;
+ int wbytes = wsamples << hw->info.shift;
if (wbytes != written) {
- dolog ("Unaligned write %d, %d\n", wbytes, written);
+ dolog ("warning: Misaligned write %d (requested %d), "
+ "alignment %d\n",
+ wbytes, written, hw->info.align + 1);
}
- memset (src, 0, wbytes);
- decr -= samples;
+ mixeng_clear (src, wsamples);
+ decr -= wsamples;
rpos = (rpos + wsamples) % hw->samples;
break;
}
}
- memset (src, 0, convert_samples * sizeof (st_sample_t));
+
+ mixeng_clear (src, convert_samples);
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
@@ -309,28 +385,24 @@ static void oss_hw_run (HWVoice *hw)
oss->old_optr = cntinfo.ptr;
}
- pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
-}
-
-static void oss_hw_fini (HWVoice *hw)
+ return decr;
+}
+
+static void oss_fini_out (HWVoiceOut *hw)
{
int err;
- OSSVoice *oss = (OSSVoice *) hw;
-
- ldebug ("oss_hw_fini\n");
- err = close (oss->fd);
- if (err) {
- dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
- }
- oss->fd = -1;
+ OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+
+ ldebug ("oss_fini\n");
+ oss_anal_close (&oss->fd);
if (oss->pcm_buf) {
if (oss->mmapped) {
- err = munmap (oss->pcm_buf, hw->bufsize);
+ err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
if (err) {
- dolog ("Failed to unmap OSS buffer\nReason: %s\n",
- errstr ());
+ oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
+ oss->pcm_buf, hw->samples << hw->info.shift);
}
}
else {
@@ -340,48 +412,79 @@ static void oss_hw_fini (HWVoice *hw)
}
}
-static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
-{
- OSSVoice *oss = (OSSVoice *) hw;
+static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
+{
+ OSSVoiceOut *oss = (OSSVoiceOut *) hw;
struct oss_params req, obt;
-
- assert (!oss->fd);
- req.fmt = AUD_to_ossfmt (fmt);
- req.freq = freq;
- req.nchannels = nchannels;
+ int endianness;
+ int err;
+ int fd;
+ audfmt_e effective_fmt;
+ audsettings_t obt_as;
+
+ oss->fd = -1;
+
+ req.fmt = aud_to_ossfmt (as->fmt);
+ req.freq = as->freq;
+ req.nchannels = as->nchannels;
req.fragsize = conf.fragsize;
req.nfrags = conf.nfrags;
- if (oss_open (&req, &obt, &oss->fd))
+ if (oss_open (0, &req, &obt, &fd)) {
return -1;
-
- hw->freq = obt.freq;
- hw->fmt = oss_to_audfmt (obt.fmt);
- hw->nchannels = obt.nchannels;
-
+ }
+
+ err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
+ if (err) {
+ oss_anal_close (&fd);
+ return -1;
+ }
+
+ 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)
+ );
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
- hw->bufsize = obt.nfrags * obt.fragsize;
+
+ if (obt.nfrags * obt.fragsize & hw->info.align) {
+ dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
+ obt.nfrags * obt.fragsize, hw->info.align + 1);
+ }
+
+ hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
oss->mmapped = 0;
if (conf.try_mmap) {
- oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
- MAP_SHARED, oss->fd, 0);
+ oss->pcm_buf = mmap (
+ 0,
+ hw->samples << hw->info.shift,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd,
+ 0
+ );
if (oss->pcm_buf == MAP_FAILED) {
- dolog ("Failed to mmap OSS device\nReason: %s\n",
- errstr ());
+ oss_logerr (errno, "Failed to map %d bytes of DAC\n",
+ hw->samples << hw->info.shift);
} else {
int err;
int trig = 0;
- if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
- dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
- errstr ());
+ if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+ oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
}
else {
trig = PCM_ENABLE_OUTPUT;
- if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
- dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
- "Reason: %s\n", errstr ());
+ if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+ oss_logerr (
+ errno,
+ "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
+ );
}
else {
oss->mmapped = 1;
@@ -389,43 +492,55 @@ static int oss_hw_init (HWVoice *hw, int
}
if (!oss->mmapped) {
- err = munmap (oss->pcm_buf, hw->bufsize);
+ err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
if (err) {
- dolog ("Failed to unmap OSS device\nReason: %s\n",
- errstr ());
+ oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
+ oss->pcm_buf, hw->samples << hw->info.shift);
}
}
}
}
if (!oss->mmapped) {
- oss->pcm_buf = qemu_mallocz (hw->bufsize);
+ oss->pcm_buf = audio_calloc (
+ AUDIO_FUNC,
+ hw->samples,
+ 1 << hw->info.shift
+ );
if (!oss->pcm_buf) {
- close (oss->fd);
- oss->fd = -1;
+ dolog (
+ "Could not allocate DAC buffer (%d samples, each %d bytes)\n",
+ hw->samples,
+ 1 << hw->info.shift
+ );
+ oss_anal_close (&fd);
return -1;
}
}
+ oss->fd = fd;
return 0;
}
-static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
+static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
int trig;
- OSSVoice *oss = (OSSVoice *) hw;
-
- if (!oss->mmapped)
+ OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+
+ if (!oss->mmapped) {
return 0;
+ }
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
- pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
+ audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
trig = PCM_ENABLE_OUTPUT;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
- dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
- "Reason: %s\n", errstr ());
+ oss_logerr (
+ errno,
+ "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
+ );
return -1;
}
break;
@@ -434,8 +549,7 @@ static int oss_hw_ctl (HWVoice *hw, int
ldebug ("disabling voice\n");
trig = 0;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
- dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
- errstr ());
+ oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
return -1;
}
break;
@@ -443,33 +557,206 @@ static int oss_hw_ctl (HWVoice *hw, int
return 0;
}
+static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
+{
+ OSSVoiceIn *oss = (OSSVoiceIn *) hw;
+ struct oss_params req, obt;
+ int endianness;
+ int err;
+ int fd;
+ audfmt_e effective_fmt;
+ audsettings_t obt_as;
+
+ oss->fd = -1;
+
+ req.fmt = aud_to_ossfmt (as->fmt);
+ req.freq = as->freq;
+ req.nchannels = as->nchannels;
+ req.fragsize = conf.fragsize;
+ req.nfrags = conf.nfrags;
+ if (oss_open (1, &req, &obt, &fd)) {
+ return -1;
+ }
+
+ err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
+ if (err) {
+ oss_anal_close (&fd);
+ return -1;
+ }
+
+ 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)
+ );
+ oss->nfrags = obt.nfrags;
+ oss->fragsize = obt.fragsize;
+
+ if (obt.nfrags * obt.fragsize & hw->info.align) {
+ dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
+ obt.nfrags * obt.fragsize, hw->info.align + 1);
+ }
+
+ hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
+ oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+ if (!oss->pcm_buf) {
+ dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
+ hw->samples, 1 << hw->info.shift);
+ oss_anal_close (&fd);
+ return -1;
+ }
+
+ oss->fd = fd;
+ return 0;
+}
+
+static void oss_fini_in (HWVoiceIn *hw)
+{
+ OSSVoiceIn *oss = (OSSVoiceIn *) hw;
+
+ oss_anal_close (&oss->fd);
+
+ if (oss->pcm_buf) {
+ qemu_free (oss->pcm_buf);
+ oss->pcm_buf = NULL;
+ }
+}
+
+static int oss_run_in (HWVoiceIn *hw)
+{
+ OSSVoiceIn *oss = (OSSVoiceIn *) hw;
+ int hwshift = hw->info.shift;
+ int i;
+ int live = audio_pcm_hw_get_live_in (hw);
+ int dead = hw->samples - live;
+ size_t read_samples = 0;
+ struct {
+ int add;
+ int len;
+ } bufs[2] = {
+ { hw->wpos, 0 },
+ { 0, 0 }
+ };
+
+ if (!dead) {
+ return 0;
+ }
+
+ if (hw->wpos + dead > hw->samples) {
+ bufs[0].len = (hw->samples - hw->wpos) << hwshift;
+ bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
+ }
+ else {
+ bufs[0].len = dead << hwshift;
+ }
+
+
+ for (i = 0; i < 2; ++i) {
+ ssize_t nread;
+
+ if (bufs[i].len) {
+ void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
+ nread = read (oss->fd, p, bufs[i].len);
+
+ if (nread > 0) {
+ if (nread & hw->info.align) {
+ dolog ("warning: Misaligned read %zd (requested %d), "
+ "alignment %d\n", nread, bufs[i].add << hwshift,
+ hw->info.align + 1);
+ }
+ read_samples += nread >> hwshift;
+ hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
+ &nominal_volume);
+ }
+
+ if (bufs[i].len - nread) {
+ if (nread == -1) {
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+ break;
+ default:
+ oss_logerr (
+ errno,
+ "Failed to read %d bytes of audio (to %p)\n",
+ bufs[i].len, p
+ );
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ hw->wpos = (hw->wpos + read_samples) % hw->samples;
+ return read_samples;
+}
+
+static int oss_read (SWVoiceIn *sw, void *buf, int size)
+{
+ return audio_pcm_sw_read (sw, buf, size);
+}
+
+static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
+{
+ (void) hw;
+ (void) cmd;
+ return 0;
+}
+
static void *oss_audio_init (void)
{
- conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
- conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
- conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
- conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
return &conf;
}
static void oss_audio_fini (void *opaque)
{
-}
-
-struct pcm_ops oss_pcm_ops = {
- oss_hw_init,
- oss_hw_fini,
- oss_hw_run,
- oss_hw_write,
- oss_hw_ctl
+ (void) opaque;
+}
+
+static struct audio_option oss_options[] = {
+ {"FRAGSIZE", AUD_OPT_INT, &conf.fragsize,
+ "Fragment size in bytes", NULL, 0},
+ {"NFRAGS", AUD_OPT_INT, &conf.nfrags,
+ "Number of fragments", NULL, 0},
+ {"MMAP", AUD_OPT_BOOL, &conf.try_mmap,
+ "Try using memory mapped access", NULL, 0},
+ {"DAC_DEV", AUD_OPT_STR, &conf.devpath_out,
+ "Path to DAC device", NULL, 0},
+ {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
+ "Path to ADC device", NULL, 0},
+ {NULL, 0, NULL, NULL, NULL, 0}
};
-struct audio_output_driver oss_output_driver = {
- "oss",
- oss_audio_init,
- oss_audio_fini,
- &oss_pcm_ops,
- 1,
- INT_MAX,
- sizeof (OSSVoice)
+static struct audio_pcm_ops oss_pcm_ops = {
+ oss_init_out,
+ oss_fini_out,
+ oss_run_out,
+ oss_write,
+ oss_ctl_out,
+
+ oss_init_in,
+ oss_fini_in,
+ oss_run_in,
+ oss_read,
+ oss_ctl_in
};
+
+struct audio_driver oss_audio_driver = {
+ INIT_FIELD (name = ) "oss",
+ INIT_FIELD (descr = ) "OSS http://www.opensound.com",
+ INIT_FIELD (options = ) oss_options,
+ INIT_FIELD (init = ) oss_audio_init,
+ INIT_FIELD (fini = ) oss_audio_fini,
+ INIT_FIELD (pcm_ops = ) &oss_pcm_ops,
+ INIT_FIELD (can_be_default = ) 1,
+ INIT_FIELD (max_voices_out = ) INT_MAX,
+ INIT_FIELD (max_voices_in = ) INT_MAX,
+ INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut),
+ INIT_FIELD (voice_size_in = ) sizeof (OSSVoiceIn)
+};
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/sdlaudio.c
--- a/tools/ioemu/audio/sdlaudio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/sdlaudio.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
- * QEMU SDL audio output driver
- *
- * Copyright (c) 2004 Vassili Karpov (malc)
- *
+ * QEMU SDL audio driver
+ *
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -25,22 +25,15 @@
#include <SDL_thread.h>
#include "vl.h"
-#include "audio/audio_int.h"
-
-typedef struct SDLVoice {
- HWVoice hw;
-} SDLVoice;
-
-#define dolog(...) AUD_log ("sdl", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
-
-#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
-
-#define errstr() SDL_GetError ()
+#define AUDIO_CAP "sdl"
+#include "audio_int.h"
+
+typedef struct SDLVoiceOut {
+ HWVoiceOut hw;
+ int live;
+ int rpos;
+ int decr;
+} SDLVoiceOut;
static struct {
int nb_samples;
@@ -56,91 +49,129 @@ struct SDLAudioState {
} glob_sdl;
typedef struct SDLAudioState SDLAudioState;
-static void sdl_hw_run (HWVoice *hw)
-{
- (void) hw;
-}
-
-static int sdl_lock (SDLAudioState *s)
+static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ AUD_vlog (AUDIO_CAP, fmt, ap);
+ va_end (ap);
+
+ AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
+}
+
+static int sdl_lock (SDLAudioState *s, const char *forfn)
{
if (SDL_LockMutex (s->mutex)) {
- dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
- return -1;
- }
- return 0;
-}
-
-static int sdl_unlock (SDLAudioState *s)
+ sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
+ return -1;
+ }
+ return 0;
+}
+
+static int sdl_unlock (SDLAudioState *s, const char *forfn)
{
if (SDL_UnlockMutex (s->mutex)) {
- dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
- return -1;
- }
- return 0;
-}
-
-static int sdl_post (SDLAudioState *s)
+ sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
+ return -1;
+ }
+ return 0;
+}
+
+static int sdl_post (SDLAudioState *s, const char *forfn)
{
if (SDL_SemPost (s->sem)) {
- dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
- return -1;
- }
- return 0;
-}
-
-static int sdl_wait (SDLAudioState *s)
+ sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
+ return -1;
+ }
+ return 0;
+}
+
+static int sdl_wait (SDLAudioState *s, const char *forfn)
{
if (SDL_SemWait (s->sem)) {
- dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
- return -1;
- }
- return 0;
-}
-
-static int sdl_unlock_and_post (SDLAudioState *s)
-{
- if (sdl_unlock (s))
- return -1;
-
- return sdl_post (s);
-}
-
-static int sdl_hw_write (SWVoice *sw, void *buf, int len)
-{
- int ret;
- SDLAudioState *s = &glob_sdl;
- sdl_lock (s);
- ret = pcm_hw_write (sw, buf, len);
- sdl_unlock_and_post (s);
- return ret;
-}
-
-static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
-{
- *shift = 0;
+ sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
+ return -1;
+ }
+ return 0;
+}
+
+static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
+{
+ if (sdl_unlock (s, forfn)) {
+ return -1;
+ }
+
+ return sdl_post (s, forfn);
+}
+
+static int aud_to_sdlfmt (audfmt_e fmt, int *shift)
+{
switch (fmt) {
- case AUD_FMT_S8: return AUDIO_S8;
- case AUD_FMT_U8: return AUDIO_U8;
- case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
- case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
+ case AUD_FMT_S8:
+ *shift = 0;
+ return AUDIO_S8;
+
+ case AUD_FMT_U8:
+ *shift = 0;
+ return AUDIO_U8;
+
+ case AUD_FMT_S16:
+ *shift = 1;
+ return AUDIO_S16LSB;
+
+ case AUD_FMT_U16:
+ *shift = 1;
+ return AUDIO_U16LSB;
+
default:
- dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
- exit (EXIT_FAILURE);
- }
-}
-
-static int sdl_to_audfmt (int fmt)
-{
- switch (fmt) {
- case AUDIO_S8: return AUD_FMT_S8;
- case AUDIO_U8: return AUD_FMT_U8;
- case AUDIO_S16LSB: return AUD_FMT_S16;
- case AUDIO_U16LSB: return AUD_FMT_U16;
+ dolog ("Internal logic error: Bad audio format %d\n", fmt);
+#ifdef DEBUG_AUDIO
+ abort ();
+#endif
+ return AUDIO_U8;
+ }
+}
+
+static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
+{
+ switch (sdlfmt) {
+ case AUDIO_S8:
+ *endianess = 0;
+ *fmt = AUD_FMT_S8;
+ break;
+
+ case AUDIO_U8:
+ *endianess = 0;
+ *fmt = AUD_FMT_U8;
+ break;
+
+ case AUDIO_S16LSB:
+ *endianess = 0;
+ *fmt = AUD_FMT_S16;
+ break;
+
+ case AUDIO_U16LSB:
+ *endianess = 0;
+ *fmt = AUD_FMT_U16;
+ break;
+
+ case AUDIO_S16MSB:
+ *endianess = 1;
+ *fmt = AUD_FMT_S16;
+ break;
+
+ case AUDIO_U16MSB:
+ *endianess = 1;
+ *fmt = AUD_FMT_U16;
+ break;
+
default:
- dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
- "Aborting\n", fmt);
- exit (EXIT_FAILURE);
- }
+ dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
+ return -1;
+ }
+
+ return 0;
}
static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
@@ -149,7 +180,7 @@ static int sdl_open (SDL_AudioSpec *req,
status = SDL_OpenAudio (req, obt);
if (status) {
- dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
+ sdl_logerr ("SDL_OpenAudio failed\n");
}
return status;
}
@@ -157,9 +188,9 @@ static void sdl_close (SDLAudioState *s)
static void sdl_close (SDLAudioState *s)
{
if (s->initialized) {
- sdl_lock (s);
+ sdl_lock (s, "sdl_close");
s->exit = 1;
- sdl_unlock_and_post (s);
+ sdl_unlock_and_post (s, "sdl_close");
SDL_PauseAudio (1);
SDL_CloseAudio ();
s->initialized = 0;
@@ -168,31 +199,40 @@ static void sdl_close (SDLAudioState *s)
static void sdl_callback (void *opaque, Uint8 *buf, int len)
{
- SDLVoice *sdl = opaque;
+ SDLVoiceOut *sdl = opaque;
SDLAudioState *s = &glob_sdl;
- HWVoice *hw = &sdl->hw;
- int samples = len >> hw->shift;
+ HWVoiceOut *hw = &sdl->hw;
+ int samples = len >> hw->info.shift;
if (s->exit) {
return;
}
while (samples) {
- int to_mix, live, decr;
+ int to_mix, decr;
/* dolog ("in callback samples=%d\n", samples); */
- sdl_wait (s);
+ sdl_wait (s, "sdl_callback");
if (s->exit) {
return;
}
- sdl_lock (s);
- live = pcm_hw_get_live (hw);
- if (live <= 0)
+ if (sdl_lock (s, "sdl_callback")) {
+ return;
+ }
+
+ if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) {
+ dolog ("sdl->live=%d hw->samples=%d\n",
+ sdl->live, hw->samples);
+ return;
+ }
+
+ if (!sdl->live) {
goto again;
+ }
/* dolog ("in callback live=%d\n", live); */
- to_mix = audio_MIN (samples, live);
+ to_mix = audio_MIN (samples, sdl->live);
decr = to_mix;
while (to_mix) {
int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
@@ -200,58 +240,109 @@ static void sdl_callback (void *opaque,
/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
hw->clip (buf, src, chunk);
- memset (src, 0, chunk * sizeof (st_sample_t));
- hw->rpos = (hw->rpos + chunk) % hw->samples;
+ mixeng_clear (src, chunk);
+ sdl->rpos = (sdl->rpos + chunk) % hw->samples;
to_mix -= chunk;
- buf += chunk << hw->shift;
+ buf += chunk << hw->info.shift;
}
samples -= decr;
- pcm_hw_dec_live (hw, decr);
+ sdl->live -= decr;
+ sdl->decr += decr;
again:
- sdl_unlock (s);
+ if (sdl_unlock (s, "sdl_callback")) {
+ return;
+ }
}
/* dolog ("done len=%d\n", len); */
}
-static void sdl_hw_fini (HWVoice *hw)
-{
- ldebug ("sdl_hw_fini %d fixed=%d\n",
- glob_sdl.initialized, audio_conf.fixed_format);
+static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
+{
+ return audio_pcm_sw_write (sw, buf, len);
+}
+
+static int sdl_run_out (HWVoiceOut *hw)
+{
+ int decr, live;
+ SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
+ SDLAudioState *s = &glob_sdl;
+
+ if (sdl_lock (s, "sdl_callback")) {
+ return 0;
+ }
+
+ live = audio_pcm_hw_get_live_out (hw);
+
+ if (sdl->decr > live) {
+ ldebug ("sdl->decr %d live %d sdl->live %d\n",
+ sdl->decr,
+ live,
+ sdl->live);
+ }
+
+ decr = audio_MIN (sdl->decr, live);
+ sdl->decr -= decr;
+
+ sdl->live = live - decr;
+ hw->rpos = sdl->rpos;
+
+ if (sdl->live > 0) {
+ sdl_unlock_and_post (s, "sdl_callback");
+ }
+ else {
+ sdl_unlock (s, "sdl_callback");
+ }
+ return decr;
+}
+
+static void sdl_fini_out (HWVoiceOut *hw)
+{
+ (void) hw;
+
sdl_close (&glob_sdl);
}
-static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
-{
- SDLVoice *sdl = (SDLVoice *) hw;
+static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as)
+{
+ SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
SDLAudioState *s = &glob_sdl;
SDL_AudioSpec req, obt;
int shift;
-
- ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
- s->initialized, freq, audio_conf.fixed_format);
-
- if (nchannels != 2) {
- dolog ("Bogus channel count %d\n", nchannels);
- return -1;
- }
-
- req.freq = freq;
- req.format = AUD_to_sdlfmt (fmt, &shift);
- req.channels = nchannels;
+ int endianess;
+ int err;
+ audfmt_e effective_fmt;
+ audsettings_t obt_as;
+
+ shift <<= as->nchannels == 2;
+
+ req.freq = as->freq;
+ req.format = aud_to_sdlfmt (as->fmt, &shift);
+ req.channels = as->nchannels;
req.samples = conf.nb_samples;
- shift <<= nchannels == 2;
-
req.callback = sdl_callback;
req.userdata = sdl;
- if (sdl_open (&req, &obt))
- return -1;
-
- hw->freq = obt.freq;
- hw->fmt = sdl_to_audfmt (obt.format);
- hw->nchannels = obt.channels;
- hw->bufsize = obt.samples << shift;
+ if (sdl_open (&req, &obt)) {
+ return -1;
+ }
+
+ err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess);
+ if (err) {
+ sdl_close (s);
+ return -1;
+ }
+
+ 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)
+ );
+ hw->samples = obt.samples;
s->initialized = 1;
s->exit = 0;
@@ -259,7 +350,7 @@ static int sdl_hw_init (HWVoice *hw, int
return 0;
}
-static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
+static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
(void) hw;
@@ -278,24 +369,22 @@ static void *sdl_audio_init (void)
static void *sdl_audio_init (void)
{
SDLAudioState *s = &glob_sdl;
- conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
- dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
- errstr ());
+ sdl_logerr ("SDL failed to initialize audio subsystem\n");
return NULL;
}
s->mutex = SDL_CreateMutex ();
if (!s->mutex) {
- dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
+ sdl_logerr ("Failed to create SDL mutex\n");
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
s->sem = SDL_CreateSemaphore (0);
if (!s->sem) {
- dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
+ sdl_logerr ("Failed to create SDL semaphore\n");
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
@@ -313,20 +402,36 @@ static void sdl_audio_fini (void *opaque
SDL_QuitSubSystem (SDL_INIT_AUDIO);
}
-struct pcm_ops sdl_pcm_ops = {
- sdl_hw_init,
- sdl_hw_fini,
- sdl_hw_run,
- sdl_hw_write,
- sdl_hw_ctl
+static struct audio_option sdl_options[] = {
+ {"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
+ "Size of SDL buffer in samples", NULL, 0},
+ {NULL, 0, NULL, NULL, NULL, 0}
};
-struct audio_output_driver sdl_output_driver = {
- "sdl",
- sdl_audio_init,
- sdl_audio_fini,
- &sdl_pcm_ops,
- 1,
- 1,
- sizeof (SDLVoice)
+static struct audio_pcm_ops sdl_pcm_ops = {
+ sdl_init_out,
+ sdl_fini_out,
+ sdl_run_out,
+ sdl_write_out,
+ sdl_ctl_out,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
+
+struct audio_driver sdl_audio_driver = {
+ INIT_FIELD (name = ) "sdl",
+ INIT_FIELD (descr = ) "SDL http://www.libsdl.org",
+ INIT_FIELD (options = ) sdl_options,
+ INIT_FIELD (init = ) sdl_audio_init,
+ INIT_FIELD (fini = ) sdl_audio_fini,
+ INIT_FIELD (pcm_ops = ) &sdl_pcm_ops,
+ INIT_FIELD (can_be_default = ) 1,
+ INIT_FIELD (max_voices_out = ) 1,
+ INIT_FIELD (max_voices_in = ) 0,
+ INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut),
+ INIT_FIELD (voice_size_in = ) 0
+};
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/audio/wavaudio.c
--- a/tools/ioemu/audio/wavaudio.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/audio/wavaudio.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,8 +1,8 @@
/*
- * QEMU WAV audio output driver
- *
- * Copyright (c) 2004 Vassili Karpov (malc)
- *
+ * QEMU WAV audio driver
+ *
+ * Copyright (c) 2004-2005 Vassili Karpov (malc)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
* in the Software without restriction, including without limitation the rights
@@ -23,47 +23,50 @@
*/
#include "vl.h"
-#include "audio/audio_int.h"
-
-typedef struct WAVVoice {
- HWVoice hw;
+#define AUDIO_CAP "wav"
+#include "audio_int.h"
+
+typedef struct WAVVoiceOut {
+ HWVoiceOut hw;
QEMUFile *f;
int64_t old_ticks;
void *pcm_buf;
int total_samples;
-} WAVVoice;
-
-#define dolog(...) AUD_log ("wav", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
+} WAVVoiceOut;
static struct {
+ audsettings_t settings;
const char *wav_path;
} conf = {
- .wav_path = "qemu.wav"
-};
-
-static void wav_hw_run (HWVoice *hw)
-{
- WAVVoice *wav = (WAVVoice *) hw;
+ {
+ 44100,
+ 2,
+ AUD_FMT_S16
+ },
+ "qemu.wav"
+};
+
+static int wav_run_out (HWVoiceOut *hw)
+{
+ WAVVoiceOut *wav = (WAVVoiceOut *) hw;
int rpos, live, decr, samples;
uint8_t *dst;
st_sample_t *src;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - wav->old_ticks;
- int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
-
- if (bytes > INT_MAX)
- samples = INT_MAX >> hw->shift;
- else
- samples = bytes >> hw->shift;
-
- live = pcm_hw_get_live (hw);
- if (live <= 0)
- return;
+ 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;
+ }
+
+ live = audio_pcm_hw_get_live_out (hw);
+ if (!live) {
+ return 0;
+ }
wav->old_ticks = now;
decr = audio_MIN (live, samples);
@@ -73,25 +76,25 @@ static void wav_hw_run (HWVoice *hw)
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
- src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
- dst = advance (wav->pcm_buf, rpos << hw->shift);
+ src = hw->mix_buf + rpos;
+ dst = advance (wav->pcm_buf, rpos << hw->info.shift);
hw->clip (dst, src, convert_samples);
- qemu_put_buffer (wav->f, dst, convert_samples << hw->shift);
- memset (src, 0, convert_samples * sizeof (st_sample_t));
+ 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;
wav->total_samples += convert_samples;
}
- pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
-}
-
-static int wav_hw_write (SWVoice *sw, void *buf, int len)
-{
- return pcm_hw_write (sw, buf, len);
+ return decr;
+}
+
+static int wav_write_out (SWVoiceOut *sw, void *buf, int len)
+{
+ return audio_pcm_sw_write (sw, buf, len);
}
/* VICE code: Store number as little endian. */
@@ -104,20 +107,25 @@ static void le_store (uint8_t *buf, uint
}
}
-static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
-{
- WAVVoice *wav = (WAVVoice *) hw;
- int bits16 = 0, stereo = audio_state.fixed_channels == 2;
+static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
+{
+ WAVVoiceOut *wav = (WAVVoiceOut *) hw;
+ int bits16 = 0, stereo = 0;
uint8_t hdr[] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
};
-
- switch (audio_state.fixed_fmt) {
+ audsettings_t wav_as = conf.settings;
+
+ (void) as;
+
+ stereo = wav_as.nchannels == 2;
+ switch (wav_as.fmt) {
case AUD_FMT_S8:
case AUD_FMT_U8:
+ bits16 = 0;
break;
case AUD_FMT_S16:
@@ -127,22 +135,25 @@ static int wav_hw_init (HWVoice *hw, int
}
hdr[34] = bits16 ? 0x10 : 0x08;
- hw->freq = 44100;
- hw->nchannels = stereo ? 2 : 1;
- hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
- hw->bufsize = 4096;
- wav->pcm_buf = qemu_mallocz (hw->bufsize);
- if (!wav->pcm_buf)
+
+ audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0));
+
+ hw->samples = 1024;
+ wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+ if (!wav->pcm_buf) {
+ dolog ("Could not allocate buffer (%d bytes)\n",
+ hw->samples << hw->info.shift);
return -1;
-
- le_store (hdr + 22, hw->nchannels, 2);
- le_store (hdr + 24, hw->freq, 4);
- le_store (hdr + 28, hw->freq << (bits16 + stereo), 4);
+ }
+
+ le_store (hdr + 22, hw->info.nchannels, 2);
+ le_store (hdr + 24, hw->info.freq, 4);
+ le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
le_store (hdr + 32, 1 << (bits16 + stereo), 2);
wav->f = fopen (conf.wav_path, "wb");
if (!wav->f) {
- dolog ("failed to open wave file `%s'\nReason: %s\n",
+ dolog ("Failed to open wave file `%s'\nReason: %s\n",
conf.wav_path, strerror (errno));
qemu_free (wav->pcm_buf);
wav->pcm_buf = NULL;
@@ -153,17 +164,17 @@ static int wav_hw_init (HWVoice *hw, int
return 0;
}
-static void wav_hw_fini (HWVoice *hw)
-{
- WAVVoice *wav = (WAVVoice *) hw;
- int stereo = hw->nchannels == 2;
+static void wav_fini_out (HWVoiceOut *hw)
+{
+ WAVVoiceOut *wav = (WAVVoiceOut *) hw;
uint8_t rlen[4];
uint8_t dlen[4];
- uint32_t rifflen = (wav->total_samples << stereo) + 36;
- uint32_t datalen = wav->total_samples << stereo;
-
- if (!wav->f || !hw->active)
+ uint32_t datalen = wav->total_samples << hw->info.shift;
+ uint32_t rifflen = datalen + 36;
+
+ if (!wav->f) {
return;
+ }
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
@@ -181,7 +192,7 @@ static void wav_hw_fini (HWVoice *hw)
wav->pcm_buf = NULL;
}
-static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
+static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
@@ -195,23 +206,50 @@ static void *wav_audio_init (void)
static void wav_audio_fini (void *opaque)
{
+ (void) opaque;
ldebug ("wav_fini");
}
-struct pcm_ops wav_pcm_ops = {
- wav_hw_init,
- wav_hw_fini,
- wav_hw_run,
- wav_hw_write,
- wav_hw_ctl
-};
-
-struct audio_output_driver wav_output_driver = {
- "wav",
- wav_audio_init,
- wav_audio_fini,
- &wav_pcm_ops,
- 1,
- 1,
- sizeof (WAVVoice)
-};
+struct audio_option wav_options[] = {
+ {"FREQUENCY", AUD_OPT_INT, &conf.settings.freq,
+ "Frequency", NULL, 0},
+
+ {"FORMAT", AUD_OPT_FMT, &conf.settings.fmt,
+ "Format", NULL, 0},
+
+ {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels,
+ "Number of channels (1 - mono, 2 - stereo)", NULL, 0},
+
+ {"PATH", AUD_OPT_STR, &conf.wav_path,
+ "Path to wave file", NULL, 0},
+ {NULL, 0, NULL, NULL, NULL, 0}
+};
+
+struct audio_pcm_ops wav_pcm_ops = {
+ wav_init_out,
+ wav_fini_out,
+ wav_run_out,
+ wav_write_out,
+ wav_ctl_out,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct audio_driver wav_audio_driver = {
+ INIT_FIELD (name = ) "wav",
+ INIT_FIELD (descr = )
+ "WAV renderer http://wikipedia.org/wiki/WAV",
+ INIT_FIELD (options = ) wav_options,
+ INIT_FIELD (init = ) wav_audio_init,
+ INIT_FIELD (fini = ) wav_audio_fini,
+ INIT_FIELD (pcm_ops = ) &wav_pcm_ops,
+ INIT_FIELD (can_be_default = ) 0,
+ INIT_FIELD (max_voices_out = ) 1,
+ INIT_FIELD (max_voices_in = ) 0,
+ INIT_FIELD (voice_size_out = ) sizeof (WAVVoiceOut),
+ INIT_FIELD (voice_size_in = ) 0
+};
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-cloop.c
--- a/tools/ioemu/block-cloop.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-cloop.c Tue Aug 01 16:51:03 2006 -0400
@@ -1,5 +1,5 @@
/*
- * QEMU System Emulator block driver
+ * QEMU Block driver for CLOOP images
*
* Copyright (c) 2004 Johannes E. Schindelin
*
@@ -32,8 +32,8 @@ typedef struct BDRVCloopState {
uint64_t* offsets;
uint32_t sectors_per_block;
uint32_t current_block;
- char* compressed_block;
- char* uncompressed_block;
+ uint8_t *compressed_block;
+ uint8_t *uncompressed_block;
z_stream zstream;
} BDRVCloopState;
@@ -89,9 +89,9 @@ cloop_close:
}
/* initialize zlib engine */
- if(!(s->compressed_block=(char*)malloc(max_compressed_block_size+1)))
+ if(!(s->compressed_block = malloc(max_compressed_block_size+1)))
goto cloop_close;
- if(!(s->uncompressed_block=(char*)malloc(s->block_size)))
+ if(!(s->uncompressed_block = malloc(s->block_size)))
goto cloop_close;
if(inflateInit(&s->zstream) != Z_OK)
goto cloop_close;
@@ -149,6 +149,8 @@ static void cloop_close(BlockDriverState
{
BDRVCloopState *s = bs->opaque;
close(s->fd);
+ if(s->n_blocks>0)
+ free(s->offsets);
free(s->compressed_block);
free(s->uncompressed_block);
inflateEnd(&s->zstream);
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-cow.c
--- a/tools/ioemu/block-cow.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-cow.c Tue Aug 01 16:51:03 2006 -0400
@@ -54,7 +54,8 @@ static int cow_probe(const uint8_t *buf,
{
const struct cow_header_v2 *cow_header = (const void *)buf;
- if (be32_to_cpu(cow_header->magic) == COW_MAGIC &&
+ if (buf_size >= sizeof(struct cow_header_v2) &&
+ be32_to_cpu(cow_header->magic) == COW_MAGIC &&
be32_to_cpu(cow_header->version) == COW_VERSION)
return 100;
else
@@ -124,7 +125,7 @@ static int cow_open(BlockDriverState *bs
return -1;
}
-static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
+static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
{
bitmap[bitnum / 8] |= (1 << (bitnum%8));
}
@@ -198,7 +199,7 @@ static int cow_write(BlockDriverState *b
if (ret != nb_sectors * 512)
return -1;
for (i = 0; i < nb_sectors; i++)
- set_bit(s->cow_bitmap, sector_num + i);
+ cow_set_bit(s->cow_bitmap, sector_num + i);
return 0;
}
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-qcow.c
--- a/tools/ioemu/block-qcow.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-qcow.c Tue Aug 01 16:51:03 2006 -0400
@@ -80,8 +80,9 @@ static int qcow_probe(const uint8_t *buf
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
-
- if (be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
+
+ if (buf_size >= sizeof(QCowHeader) &&
+ be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
be32_to_cpu(cow_header->version) == QCOW_VERSION)
return 100;
else
@@ -551,15 +552,28 @@ static int qcow_create(const char *filen
header_size = sizeof(header);
backing_filename_len = 0;
if (backing_file) {
- realpath(backing_file, backing_filename);
- if (stat(backing_filename, &st) != 0) {
- return -1;
- }
+ if (strcmp(backing_file, "fat:")) {
+ const char *p;
+ /* XXX: this is a hack: we do not attempt to check for URL
+ like syntax */
+ p = strchr(backing_file, ':');
+ if (p && (p - backing_file) >= 2) {
+ /* URL like but exclude "c:" like filenames */
+ pstrcpy(backing_filename, sizeof(backing_filename),
+ backing_file);
+ } else {
+ realpath(backing_file, backing_filename);
+ if (stat(backing_filename, &st) != 0) {
+ return -1;
+ }
+ }
+ header.backing_file_offset = cpu_to_be64(header_size);
+ backing_filename_len = strlen(backing_filename);
+ header.backing_file_size = cpu_to_be32(backing_filename_len);
+ header_size += backing_filename_len;
+ } else
+ backing_file = NULL;
header.mtime = cpu_to_be32(st.st_mtime);
- header.backing_file_offset = cpu_to_be64(header_size);
- backing_filename_len = strlen(backing_filename);
- header.backing_file_size = cpu_to_be32(backing_filename_len);
- header_size += backing_filename_len;
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
unmodifyed sectors */
header.l2_bits = 12; /* 32 KB L2 tables */
@@ -589,6 +603,24 @@ static int qcow_create(const char *filen
write(fd, &tmp, sizeof(tmp));
}
close(fd);
+ return 0;
+}
+
+int qcow_make_empty(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint32_t l1_length = s->l1_size * sizeof(uint64_t);
+
+ memset(s->l1_table, 0, l1_length);
+ lseek(s->fd, s->l1_table_offset, SEEK_SET);
+ if (write(s->fd, s->l1_table, l1_length) < 0)
+ return -1;
+ ftruncate(s->fd, s->l1_table_offset + l1_length);
+
+ memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+ memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
+ memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
+
return 0;
}
@@ -672,6 +704,7 @@ BlockDriver bdrv_qcow = {
qcow_create,
qcow_is_allocated,
qcow_set_key,
+ qcow_make_empty
};
diff -r a75c389e4a7d -r 5ecfc7102cca tools/ioemu/block-vmdk.c
--- a/tools/ioemu/block-vmdk.c Tue Aug 01 16:42:48 2006 -0400
+++ b/tools/ioemu/block-vmdk.c Tue Aug 01 16:51:03 2006 -0400
@@ -2,6 +2,7 @@
* Block driver for the VMDK format
*
* Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2005 Filip Navara
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
deal
@@ -24,9 +25,6 @@
#include "vl.h"
#include "block_int.h"
-/* XXX: this code is untested */
-/* XXX: add write support */
-
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
@@ -56,14 +54,16 @@ typedef struct {
int64_t grain_offset;
char filler[1];
char check_bytes[4];
-} VMDK4Header;
+} __attribute__((packed)) VMDK4Header;
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
int fd;
int64_t l1_table_offset;
+ int64_t l1_backup_table_offset;
uint32_t *l1_table;
+ uint32_t *l1_backup_table;
unsigned int l1_size;
uint32_t l1_entry_sectors;
@@ -96,9 +96,13 @@ static int vmdk_open(BlockDriverState *b
uint32_t magic;
int l1_size;
- fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
- if (fd < 0)
- return -1;
+ fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+ if (fd < 0) {
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ bs->read_only = 1;
+ }
if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = be32_to_cpu(magic);
@@ -111,22 +115,24 @@ static int vmdk_open(BlockDriverState *b
s->l2_size = 1 << 9;
s->l1_size = 1 << 6;
bs->total_sectors = le32_to_cpu(header.disk_sectors);
- s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512;
+ s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9;
+ s->l1_backup_table_offset = 0;
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
- bs->total_sectors = le32_to_cpu(header.capacity);
- s->cluster_sectors = le32_to_cpu(header.granularity);
+ bs->total_sectors = le64_to_cpu(header.capacity);
+ s->cluster_sectors = le64_to_cpu(header.granularity);
s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
if (s->l1_entry_sectors <= 0)
goto fail;
s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
/ s->l1_entry_sectors;
- s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512;
+ s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
+ s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
} else {
goto fail;
}
@@ -143,14 +149,26 @@ static int vmdk_open(BlockDriverState *b
le32_to_cpus(&s->l1_table[i]);
}
+ if (s->l1_backup_table_offset) {
+ s->l1_backup_table = qemu_malloc(l1_size);
+ if (!s->l1_backup_table)
+ goto fail;
+ if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
+ goto fail;
+ if (read(fd, s->l1_backup_table, l1_size) != l1_size)
+ goto fail;
+ for(i = 0; i < s->l1_size; i++) {
+ le32_to_cpus(&s->l1_backup_table[i]);
+ }
+ }
+
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
if (!s->l2_cache)
goto fail;
s->fd = fd;
- /* XXX: currently only read only */
- bs->read_only = 1;
return 0;
fail:
+ qemu_free(s->l1_backup_table);
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(fd);
@@ -158,12 +176,12 @@ static int vmdk_open(BlockDriverState *b
}
static uint64_t get_cluster_offset(BlockDriverState *bs,
- uint64_t offset)
+ uint64_t offset, int allocate)
{
BDRVVmdkState *s = bs->opaque;
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
- uint32_t min_count, *l2_table;
+ uint32_t min_count, *l2_table, tmp;
uint64_t cluster_offset;
l1_index = (offset >> 9) / s->l1_entry_sectors;
@@ -172,7 +190,6 @@ static uint64_t get_cluster_offset(Block
l2_offset = s->l1_table[l1_index];
if (!l2_offset)
return 0;
-
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
@@ -204,6 +221,26 @@ static uint64_t get_cluster_offset(Block
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
+ if (!cluster_offset) {
+ if (!allocate)
+ return 0;
+ cluster_offset = lseek(s->fd, 0, SEEK_END);
+ ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
+ cluster_offset >>= 9;
+ /* update L2 table */
+ tmp = cpu_to_le32(cluster_offset);
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|