[Spice-commits] 715 commits - .gitignore .gitmodules HACKING MAINTAINERS Makefile Makefile.objs Makefile.target acl.c arch_init.c arch_init.h arm-semi.c audio/audio.c audio/noaudio.c audio/sdlaudio.c audio/spiceaudio.c audio/wavaudio.c balloon.c bitmap.c bitmap.h bitops.c bitops.h block-migration.c block.c block.h block/nbd.c block/qcow.c block/qcow2-cluster.c block/qcow2.c block/qed-check.c block/qed-cluster.c block/qed.c block/qed.h block/sheepdog.c block/vdi.c block/vpc.c blockdev.c bt-host.c bt-vhci.c buffered_file.c check-qdict.c compatfd.c configure console.c console.h cpu-all.h cpu-common.h cpu-defs.h cpu-exec.c cpus.c cpus.h cutils.c default-configs/i386-softmmu.mak default-configs/lm32-softmmu.mak default-configs/microblaze-softmmu.mak default-configs/microblazeel-linux-user.mak default-configs/microblazeel-softmmu.mak default-configs/unicore32-linux-user.mak default-configs/x86_64-softmmu.mak device_tree.c device_tree.h disas.c docs/ccid.txt docs/libcacard.txt docs/specs d ocs/tracing.txt elf.h exec-all.h exec.c fpu/softfloat-macros.h fpu/softfloat-native.c fpu/softfloat-native.h fpu/softfloat-specialize.h fpu/softfloat.c fpu/softfloat.h gdbstub.c gen-icount.h hmp-commands.hx hw/acpi.c hw/acpi.h hw/acpi_piix4.c hw/adb.c hw/adlib.c hw/ads7846.c hw/an5206.c hw/apic.c hw/applesmc.c hw/arm_boot.c hw/arm_gic.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/armv7m_nvic.c hw/axis_dev88.c hw/baum.c hw/blizzard.c hw/bt-hci-csr.c hw/bt-hci.c hw/ccid-card-emulated.c hw/ccid-card-passthru.c hw/ccid.h hw/cirrus_vga.c hw/collie.c hw/cris-boot.c hw/cuda.c hw/dp8393x.c hw/dummy_m68k.c hw/e1000.c hw/eepro100.c hw/empty_slot.c hw/etraxfs.c hw/etraxfs_timer.c hw/fdc.c hw/fdc.h hw/flash.h hw/fmopl.c hw/grackle_pci.c hw/grlib_apbuart.c hw/grlib_gptimer.c hw/grlib_irqmp.c hw/gt64xxx.c hw/gumstix.c hw/heathrow_pic.c hw/hpet.c hw/hw.h hw/i8254.c hw/i8259.c hw/ide hw/ide.h hw/integratorcp.c hw/intel-hda.c hw/irq.c hw/irq.h hw/isa-bus.c hw/isa.h hw/kvmclock.c hw/kvmcloc k.h hw/lan9118.c hw/lm32.h hw/lm32_boards.c hw/lm32_hwsetup.h hw/lm32_juart.c hw/lm32_juart.h hw/lm32_pic.c hw/lm32_pic.h hw/lm32_sys.c hw/lm32_timer.c hw/lm32_uart.c hw/lm832x.c hw/lsi53c895a.c hw/m48t59.c hw/mac_dbdma.c hw/mac_nvram.c hw/mainstone.c hw/max111x.c hw/mc146818rtc.c hw/milkymist-ac97.c hw/milkymist-hpdmc.c hw/milkymist-hw.h hw/milkymist-memcard.c hw/milkymist-minimac.c hw/milkymist-pfpu.c hw/milkymist-softusb.c hw/milkymist-sysctl.c hw/milkymist-tmu2.c hw/milkymist-uart.c hw/milkymist-vgafb.c hw/milkymist-vgafb_template.h hw/milkymist.c hw/mips_fulong2e.c hw/mips_jazz.c hw/mips_malta.c hw/mips_r4k.c hw/mips_timer.c hw/mipsnet.c hw/mpcore.c hw/mst_fpga.c hw/multiboot.c hw/musicpal.c hw/nand.c hw/ne2000-isa.c hw/ne2000.c hw/omap1.c hw/omap_gptimer.c hw/omap_sx1.c hw/omap_synctimer.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/pci_host.c hw/pci_internals.h hw/pcie.c hw/pcie_aer.c hw/pcie_host.c hw/pcnet-pci.c hw/pcnet.c hw/pcs pk.c hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/piix4.c hw/pl011.c hw/pl022.c hw/pl031.c hw/pl061.c hw/pl181.c hw/ppc-viosrp.h hw/ppc.c hw/ppc.h hw/ppc405_boards.c hw/ppc405_uc.c hw/ppc440_bamboo.c hw/ppc4xx_devs.c hw/ppc4xx_pci.c hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/ppce500_pci.c hw/primecell.h hw/ps2.c hw/ptimer.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_keypad.c hw/pxa2xx_lcd.c hw/pxa2xx_mmci.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/qdev-properties.c hw/qdev.c hw/rc4030.c hw/realview.c hw/rtl8139.c hw/s390-virtio-bus.c hw/s390-virtio-bus.h hw/s390-virtio.c hw/sb16.c hw/scsi-disk.c hw/sd.c hw/serial.c hw/sm501_template.h hw/smbus.h hw/smbus_eeprom.c hw/soc_dma.c hw/spapr.c hw/spapr.h hw/spapr_hcall.c hw/spapr_llan.c hw/spapr_rtas.c hw/spapr_vio.c hw/spapr_vio.h hw/spapr_vscsi.c hw/spapr_vty.c hw/spitz.c hw/srp.h hw/stellaris.c hw/stellaris_input.c hw/strongarm.c h w/strongarm.h hw/sun4m.c hw/sun4u.c hw/syborg.c hw/syborg_keyboard.c hw/syborg_pointer.c hw/syborg_rtc.c hw/syborg_serial.c hw/syborg_timer.c hw/syborg_virtio.c hw/sysbus.c hw/tc58128.c hw/tosa.c hw/tsc2005.c hw/tsc210x.c hw/tusb6010.c hw/twl92230.c hw/unin_pci.c hw/usb-ccid.c hw/usb-hid.c hw/usb-msd.c hw/usb-musb.c hw/usb-ohci.c hw/usb-uhci.c hw/versatilepb.c hw/vexpress.c hw/vga-isa.c hw/vga.c hw/vga_int.h hw/vhost.c hw/virtio-9p.c hw/virtio-balloon.c hw/virtio-blk.c hw/virtio-console.c hw/virtio-net.c hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/virtio.c hw/virtio.h hw/vmmouse.c hw/vmport.c hw/vt82c686.c hw/watchdog.c hw/wdt_i6300esb.c hw/wdt_ib700.c hw/xen_console.c hw/xen_disk.c hw/xen_domainbuild.c hw/xen_machine_pv.c hw/xenfb.c hw/xics.c hw/xics.h hw/xilinx.h hw/xilinx_axidma.c hw/xilinx_axidma.h hw/xilinx_axienet.c hw/xilinx_ethlite.c hw/xilinx_timer.c input.c iohandler.c ioport.c json-lexer.c kvm-all.c kvm-stub.c kvm.h libcacard/Makefile libcacard/ca c.c libcacard/cac.h libcacard/card_7816.c libcacard/card_7816.h libcacard/card_7816t.h libcacard/event.c libcacard/eventt.h libcacard/link_test.c libcacard/vcard.c libcacard/vcard.h libcacard/vcard_emul.h libcacard/vcard_emul_nss.c libcacard/vcard_emul_type.c libcacard/vcard_emul_type.h libcacard/vcardt.h libcacard/vevent.h libcacard/vreader.c libcacard/vreader.h libcacard/vreadert.h libcacard/vscard_common.h libcacard/vscclient.c linux-user/alpha linux-user/arm linux-user/elfload.c linux-user/ioctls.h linux-user/main.c linux-user/mmap.c linux-user/qemu.h linux-user/strace.c linux-user/strace.list linux-user/syscall.c linux-user/syscall_defs.h linux-user/unicore32 migration-exec.c migration-fd.c migration-tcp.c migration-unix.c migration.c migration.h monitor.c nbd.c nbd.h net-checksum.c net.c net/dump.c net/slirp.c net/socket.c net/tap-win32.c net/vde.c os-posix.c os-win32.c osdep.c osdep.h oslib-win32.c pc-bios/README pc-bios/bios.bin pc-bios/gpxe-eepro100-80861209.rom pc- bios/linuxboot.bin pc-bios/multiboot.bin pc-bios/optionrom pc-bios/petalogix-ml605.dtb pc-bios/pxe-e1000.bin pc-bios/pxe-e1000.rom pc-bios/pxe-eepro100.rom pc-bios/pxe-ne2k_pci.bin pc-bios/pxe-ne2k_pci.rom pc-bios/pxe-pcnet.bin pc-bios/pxe-pcnet.rom pc-bios/pxe-rtl8139.bin pc-bios/pxe-rtl8139.rom pc-bios/pxe-virtio.bin pc-bios/pxe-virtio.rom pc-bios/slof.bin pc-bios/spapr-rtas pc-bios/spapr-rtas.bin poison.h posix-aio-compat.c qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-error.c qemu-img-cmds.hx qemu-img.c qemu-lock.h qemu-options.hx qemu-os-win32.h qemu-progress.c qemu-sockets.c qemu-thread-posix.c qemu-thread-posix.h qemu-thread-win32.c qemu-thread-win32.h qemu-thread.c qemu-thread.h qemu-timer.c qemu-timer.h qemu-tool.c qemu_socket.h qerror.c qerror.h qmp-commands.hx roms/SLOF roms/ipxe roms/seabios savevm.c scripts/refresh-pxe-roms.sh scripts/simpletrace.py scripts/tracetool simpletrace.c simpletrace.h slirp/bootp.c slirp/misc.c slirp/slirp.c slirp/tftp.c sli rp/tftp.h sysemu.h target-alpha/exec.h target-alpha/op_helper.c target-alpha/translate.c target-arm/cpu.h target-arm/exec.h target-arm/helper.c target-arm/helper.h target-arm/helpers.h target-arm/iwmmxt_helper.c target-arm/machine.c target-arm/neon_helper.c target-arm/op_helper.c target-arm/translate.c target-cris/exec.h target-cris/op_helper.c target-cris/translate.c target-i386/cpu.h target-i386/cpuid.c target-i386/exec.h target-i386/helper.c target-i386/kvm.c target-i386/kvm_x86.h target-i386/op_helper.c target-i386/ops_sse.h target-i386/translate.c target-lm32/README target-lm32/TODO target-lm32/cpu.h target-lm32/exec.h target-lm32/helper.c target-lm32/helper.h target-lm32/machine.c target-lm32/op_helper.c target-lm32/translate.c target-m68k/exec.h target-m68k/op_helper.c target-m68k/translate.c target-microblaze/cpu.h target-microblaze/exec.h target-microblaze/helper.h target-microblaze/microblaze-decode.h target-microblaze/op_helper.c target-microblaze/translate.c targ et-mips/cpu.h target-mips/exec.h target-mips/op_helper.c target-mips/translate.c target-ppc/cpu.h target-ppc/exec.h target-ppc/helper.c target-ppc/helper.h target-ppc/kvm.c target-ppc/kvm_ppc.c target-ppc/kvm_ppc.h target-ppc/machine.c target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu.h target-s390x/exec.h target-s390x/helper.c target-s390x/kvm.c target-s390x/op_helper.c target-s390x/translate.c target-sh4/cpu.h target-sh4/exec.h target-sh4/helper.c target-sh4/helper.h target-sh4/op_helper.c target-sh4/translate.c target-sparc/exec.h target-sparc/op_helper.c target-sparc/translate.c target-unicore32/cpu.h target-unicore32/exec.h target-unicore32/helper.c target-unicore32/helper.h target-unicore32/op_helper.c target-unicore32/translate.c tcg/arm tcg/tcg.c tcg/tcg.h tests/Makefile tests/cris tests/linux-test.c tests/lm32 tests/test-mmap.c trace-events translate-all.c ui/sdl.c ui/spice-core.c ui/vnc-enc-tight.c ui/vnc-enc-zlib.c ui/vnc-e nc-zrle-template.c ui/vnc-enc-zrle.c ui/vnc-enc-zrle.h ui/vnc-enc-zywrle-template.c ui/vnc-enc-zywrle.h ui/vnc-jobs-async.c ui/vnc-palette.c ui/vnc-palette.h ui/vnc.c ui/vnc.h ui/vnc_keysym.h usb-bsd.c usb-linux.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Fri Apr 29 00:40:59 PDT 2011


 .gitignore                                  |    5 
 .gitmodules                                 |    6 
 HACKING                                     |    3 
 MAINTAINERS                                 |   17 
 Makefile                                    |   64 
 Makefile.objs                               |   73 
 Makefile.target                             |   55 
 acl.c                                       |    1 
 arch_init.c                                 |    2 
 arch_init.h                                 |   15 
 arm-semi.c                                  |    1 
 audio/audio.c                               |    4 
 audio/noaudio.c                             |    4 
 audio/sdlaudio.c                            |   20 
 audio/spiceaudio.c                          |    4 
 audio/wavaudio.c                            |    2 
 balloon.c                                   |    1 
 bitmap.c                                    |  256 +++
 bitmap.h                                    |  222 ++
 bitops.c                                    |  142 +
 bitops.h                                    |  272 +++
 block-migration.c                           |    2 
 block.c                                     |  141 +
 block.h                                     |   11 
 block/nbd.c                                 |  157 +
 block/qcow.c                                |   16 
 block/qcow2-cluster.c                       |   13 
 block/qcow2.c                               |   26 
 block/qed-check.c                           |    5 
 block/qed-cluster.c                         |   31 
 block/qed.c                                 |   30 
 block/qed.h                                 |   26 
 block/sheepdog.c                            |   15 
 block/vdi.c                                 |    9 
 block/vpc.c                                 |    8 
 blockdev.c                                  |   62 
 bt-host.c                                   |    1 
 bt-vhci.c                                   |    1 
 buffered_file.c                             |    7 
 check-qdict.c                               |    3 
 compatfd.c                                  |   36 
 configure                                   |  288 ++-
 console.c                                   |   50 
 console.h                                   |   28 
 cpu-all.h                                   |   29 
 cpu-common.h                                |   11 
 cpu-defs.h                                  |   16 
 cpu-exec.c                                  |   74 
 cpus.c                                      |  802 +++++----
 cpus.h                                      |    7 
 cutils.c                                    |   31 
 default-configs/i386-softmmu.mak            |    1 
 default-configs/lm32-softmmu.mak            |    6 
 default-configs/microblaze-softmmu.mak      |    1 
 default-configs/microblazeel-linux-user.mak |    1 
 default-configs/microblazeel-softmmu.mak    |    5 
 default-configs/unicore32-linux-user.mak    |    1 
 default-configs/x86_64-softmmu.mak          |    3 
 dev/null                                    |binary
 device_tree.c                               |    3 
 device_tree.h                               |    2 
 disas.c                                     |    8 
 docs/ccid.txt                               |  135 +
 docs/libcacard.txt                          |  483 +++++
 docs/specs/qcow2.txt                        |  260 +++
 docs/specs/qed_spec.txt                     |    8 
 docs/tracing.txt                            |   50 
 elf.h                                       |    3 
 exec-all.h                                  |    7 
 exec.c                                      |  130 +
 fpu/softfloat-macros.h                      |  216 +-
 fpu/softfloat-native.c                      |   32 
 fpu/softfloat-native.h                      |   63 
 fpu/softfloat-specialize.h                  |  166 -
 fpu/softfloat.c                             | 1042 ++++++++----
 fpu/softfloat.h                             |  211 +-
 gdbstub.c                                   |  138 +
 gen-icount.h                                |    2 
 hmp-commands.hx                             |   32 
 hw/acpi.c                                   |  197 ++
 hw/acpi.h                                   |   68 
 hw/acpi_piix4.c                             |  225 --
 hw/adb.c                                    |   83 
 hw/adlib.c                                  |    2 
 hw/ads7846.c                                |   41 
 hw/an5206.c                                 |    1 
 hw/apic.c                                   |    8 
 hw/applesmc.c                               |    2 
 hw/arm_boot.c                               |   25 
 hw/arm_gic.c                                |    4 
 hw/arm_sysctl.c                             |  113 +
 hw/arm_timer.c                              |   66 
 hw/armv7m.c                                 |    1 
 hw/armv7m_nvic.c                            |   47 
 hw/axis_dev88.c                             |    1 
 hw/baum.c                                   |    4 
 hw/blizzard.c                               |    1 
 hw/bt-hci-csr.c                             |    5 
 hw/bt-hci.c                                 |   12 
 hw/ccid-card-emulated.c                     |  595 +++++++
 hw/ccid-card-passthru.c                     |  339 ++++
 hw/ccid.h                                   |   59 
 hw/cirrus_vga.c                             |    1 
 hw/collie.c                                 |   69 
 hw/cris-boot.c                              |    1 
 hw/cuda.c                                   |  140 -
 hw/dp8393x.c                                |    6 
 hw/dummy_m68k.c                             |    1 
 hw/e1000.c                                  |   90 -
 hw/eepro100.c                               |    2 
 hw/empty_slot.c                             |   21 
 hw/etraxfs.c                                |    1 
 hw/etraxfs_timer.c                          |    2 
 hw/fdc.c                                    |  206 --
 hw/fdc.h                                    |   29 
 hw/flash.h                                  |    4 
 hw/fmopl.c                                  |    6 
 hw/grackle_pci.c                            |   19 
 hw/grlib_apbuart.c                          |    2 
 hw/grlib_gptimer.c                          |   29 
 hw/grlib_irqmp.c                            |    4 
 hw/gt64xxx.c                                |   21 
 hw/gumstix.c                                |    1 
 hw/heathrow_pic.c                           |   62 
 hw/hpet.c                                   |   15 
 hw/hw.h                                     |  128 +
 hw/i8254.c                                  |   75 
 hw/i8259.c                                  |    4 
 hw/ide.h                                    |    3 
 hw/ide/core.c                               |  265 ++-
 hw/ide/ich.c                                |    1 
 hw/ide/internal.h                           |    6 
 hw/ide/isa.c                                |    1 
 hw/ide/macio.c                              |    1 
 hw/ide/microdrive.c                         |    1 
 hw/ide/mmio.c                               |    1 
 hw/ide/pci.c                                |    1 
 hw/ide/piix.c                               |    2 
 hw/ide/via.c                                |    2 
 hw/integratorcp.c                           |    1 
 hw/intel-hda.c                              |    2 
 hw/irq.c                                    |   15 
 hw/irq.h                                    |    5 
 hw/isa-bus.c                                |   17 
 hw/isa.h                                    |    2 
 hw/kvmclock.c                               |  125 +
 hw/kvmclock.h                               |   14 
 hw/lan9118.c                                |   10 
 hw/lm32.h                                   |   25 
 hw/lm32_boards.c                            |  304 +++
 hw/lm32_hwsetup.h                           |  178 ++
 hw/lm32_juart.c                             |  150 +
 hw/lm32_juart.h                             |   11 
 hw/lm32_pic.c                               |  190 ++
 hw/lm32_pic.h                               |   11 
 hw/lm32_sys.c                               |  161 +
 hw/lm32_timer.c                             |  222 ++
 hw/lm32_uart.c                              |  288 +++
 hw/lm832x.c                                 |    6 
 hw/lsi53c895a.c                             |   68 
 hw/m48t59.c                                 |   42 
 hw/mac_dbdma.c                              |   83 
 hw/mac_nvram.c                              |   32 
 hw/mainstone.c                              |   10 
 hw/max111x.c                                |   51 
 hw/mc146818rtc.c                            |   16 
 hw/milkymist-ac97.c                         |  335 +++
 hw/milkymist-hpdmc.c                        |  161 +
 hw/milkymist-hw.h                           |  204 ++
 hw/milkymist-memcard.c                      |  294 +++
 hw/milkymist-minimac.c                      |  568 ++++++
 hw/milkymist-pfpu.c                         |  536 ++++++
 hw/milkymist-softusb.c                      |  357 ++++
 hw/milkymist-sysctl.c                       |  330 +++
 hw/milkymist-tmu2.c                         |  481 +++++
 hw/milkymist-uart.c                         |  180 ++
 hw/milkymist-vgafb.c                        |  318 +++
 hw/milkymist-vgafb_template.h               |   74 
 hw/milkymist.c                              |  216 ++
 hw/mips_fulong2e.c                          |   22 
 hw/mips_jazz.c                              |    4 
 hw/mips_malta.c                             |   28 
 hw/mips_r4k.c                               |   14 
 hw/mips_timer.c                             |   10 
 hw/mipsnet.c                                |   53 
 hw/mpcore.c                                 |    6 
 hw/mst_fpga.c                               |   33 
 hw/multiboot.c                              |    2 
 hw/musicpal.c                               |    4 
 hw/nand.c                                   |   79 
 hw/ne2000-isa.c                             |   13 
 hw/ne2000.c                                 |    2 
 hw/omap1.c                                  |   30 
 hw/omap_gptimer.c                           |   14 
 hw/omap_sx1.c                               |    1 
 hw/omap_synctimer.c                         |    2 
 hw/parallel.c                               |   21 
 hw/pc.c                                     |   55 
 hw/pc.h                                     |   98 -
 hw/pc_piix.c                                |   61 
 hw/pci-hotplug.c                            |    5 
 hw/pci.c                                    |   13 
 hw/pci.h                                    |    9 
 hw/pci_host.c                               |    2 
 hw/pci_internals.h                          |    4 
 hw/pcie.c                                   |    3 
 hw/pcie_aer.c                               |   12 
 hw/pcie_host.c                              |    3 
 hw/pcnet-pci.c                              |    2 
 hw/pcnet.c                                  |   79 
 hw/pcspk.c                                  |    6 
 hw/petalogix_ml605_mmu.c                    |  266 +++
 hw/petalogix_s3adsp1800_mmu.c               |   11 
 hw/pflash_cfi01.c                           |    2 
 hw/pflash_cfi02.c                           |    8 
 hw/piix4.c                                  |   44 
 hw/pl011.c                                  |   76 
 hw/pl022.c                                  |   84 
 hw/pl031.c                                  |    8 
 hw/pl061.c                                  |   23 
 hw/pl181.c                                  |    6 
 hw/ppc-viosrp.h                             |  216 ++
 hw/ppc.c                                    |   87 -
 hw/ppc.h                                    |    1 
 hw/ppc405_boards.c                          |    1 
 hw/ppc405_uc.c                              |    6 
 hw/ppc440_bamboo.c                          |    3 
 hw/ppc4xx_devs.c                            |    1 
 hw/ppc4xx_pci.c                             |   80 
 hw/ppc_newworld.c                           |   11 
 hw/ppc_oldworld.c                           |   11 
 hw/ppc_prep.c                               |   18 
 hw/ppce500_mpc8544ds.c                      |    2 
 hw/ppce500_pci.c                            |   89 -
 hw/primecell.h                              |    4 
 hw/ps2.c                                    |   40 
 hw/ptimer.c                                 |   73 
 hw/pxa.h                                    |   53 
 hw/pxa2xx.c                                 |  491 +++--
 hw/pxa2xx_dma.c                             |  215 +-
 hw/pxa2xx_gpio.c                            |   11 
 hw/pxa2xx_keypad.c                          |  161 -
 hw/pxa2xx_lcd.c                             |  138 -
 hw/pxa2xx_mmci.c                            |   16 
 hw/pxa2xx_pic.c                             |   89 -
 hw/pxa2xx_timer.c                           |  294 +--
 hw/qdev-properties.c                        |    9 
 hw/qdev.c                                   |    3 
 hw/rc4030.c                                 |    8 
 hw/realview.c                               |   47 
 hw/rtl8139.c                                |  637 ++++---
 hw/s390-virtio-bus.c                        |   25 
 hw/s390-virtio-bus.h                        |    4 
 hw/s390-virtio.c                            |   26 
 hw/sb16.c                                   |    4 
 hw/scsi-disk.c                              |    2 
 hw/sd.c                                     |    6 
 hw/serial.c                                 |   32 
 hw/sm501_template.h                         |    2 
 hw/smbus.h                                  |    3 
 hw/smbus_eeprom.c                           |   22 
 hw/soc_dma.c                                |    4 
 hw/spapr.c                                  |  475 +++++
 hw/spapr.h                                  |  301 +++
 hw/spapr_hcall.c                            |  525 ++++++
 hw/spapr_llan.c                             |  518 ++++++
 hw/spapr_rtas.c                             |  278 +++
 hw/spapr_vio.c                              |  731 ++++++++
 hw/spapr_vio.h                              |  112 +
 hw/spapr_vscsi.c                            |  988 +++++++++++
 hw/spapr_vty.c                              |  159 +
 hw/spitz.c                                  |    6 
 hw/srp.h                                    |  240 ++
 hw/stellaris.c                              |  332 +--
 hw/stellaris_input.c                        |   50 
 hw/strongarm.c                              | 1598 ++++++++++++++++++
 hw/strongarm.h                              |   64 
 hw/sun4m.c                                  |   10 
 hw/sun4u.c                                  |   25 
 hw/syborg.c                                 |    1 
 hw/syborg_keyboard.c                        |   57 
 hw/syborg_pointer.c                         |   73 
 hw/syborg_rtc.c                             |   36 
 hw/syborg_serial.c                          |   60 
 hw/syborg_timer.c                           |   46 
 hw/syborg_virtio.c                          |    1 
 hw/sysbus.c                                 |    1 
 hw/tc58128.c                                |    1 
 hw/tosa.c                                   |    1 
 hw/tsc2005.c                                |    4 
 hw/tsc210x.c                                |   20 
 hw/tusb6010.c                               |    8 
 hw/twl92230.c                               |    9 
 hw/unin_pci.c                               |   21 
 hw/usb-ccid.c                               | 1419 ++++++++++++++++
 hw/usb-hid.c                                |    8 
 hw/usb-msd.c                                |    4 
 hw/usb-musb.c                               |    4 
 hw/usb-ohci.c                               |   22 
 hw/usb-uhci.c                               |    6 
 hw/versatilepb.c                            |    2 
 hw/vexpress.c                               |  224 ++
 hw/vga-isa.c                                |   51 
 hw/vga.c                                    |   55 
 hw/vga_int.h                                |    1 
 hw/vhost.c                                  |    6 
 hw/virtio-9p.c                              |    9 
 hw/virtio-balloon.c                         |    3 
 hw/virtio-blk.c                             |   10 
 hw/virtio-console.c                         |   33 
 hw/virtio-net.c                             |   13 
 hw/virtio-pci.c                             |   33 
 hw/virtio-serial-bus.c                      |   46 
 hw/virtio-serial.h                          |   14 
 hw/virtio.c                                 |    1 
 hw/virtio.h                                 |    4 
 hw/vmmouse.c                                |    2 
 hw/vmport.c                                 |   12 
 hw/vt82c686.c                               |  110 -
 hw/watchdog.c                               |    2 
 hw/wdt_i6300esb.c                           |    4 
 hw/wdt_ib700.c                              |    4 
 hw/xen_console.c                            |    1 
 hw/xen_disk.c                               |   12 
 hw/xen_domainbuild.c                        |    7 
 hw/xen_machine_pv.c                         |    1 
 hw/xenfb.c                                  |    1 
 hw/xics.c                                   |  496 +++++
 hw/xics.h                                   |   38 
 hw/xilinx.h                                 |   39 
 hw/xilinx_axidma.c                          |  509 ++++++
 hw/xilinx_axidma.h                          |   39 
 hw/xilinx_axienet.c                         |  898 ++++++++++
 hw/xilinx_ethlite.c                         |   17 
 hw/xilinx_timer.c                           |    1 
 input.c                                     |   14 
 iohandler.c                                 |  193 ++
 ioport.c                                    |    6 
 json-lexer.c                                |    6 
 kvm-all.c                                   |  123 -
 kvm-stub.c                                  |   16 
 kvm.h                                       |   20 
 libcacard/Makefile                          |   25 
 libcacard/cac.c                             |  403 ++++
 libcacard/cac.h                             |   23 
 libcacard/card_7816.c                       |  763 +++++++++
 libcacard/card_7816.h                       |   62 
 libcacard/card_7816t.h                      |  165 +
 libcacard/event.c                           |  106 +
 libcacard/eventt.h                          |   29 
 libcacard/link_test.c                       |   22 
 libcacard/vcard.c                           |  339 ++++
 libcacard/vcard.h                           |   86 +
 libcacard/vcard_emul.h                      |   65 
 libcacard/vcard_emul_nss.c                  | 1157 +++++++++++++
 libcacard/vcard_emul_type.c                 |   57 
 libcacard/vcard_emul_type.h                 |   32 
 libcacard/vcardt.h                          |   64 
 libcacard/vevent.h                          |   27 
 libcacard/vreader.c                         |  513 ++++++
 libcacard/vreader.h                         |   55 
 libcacard/vreadert.h                        |   24 
 libcacard/vscard_common.h                   |  178 ++
 libcacard/vscclient.c                       |  652 +++++++
 linux-user/alpha/syscall_nr.h               |    7 
 linux-user/arm/nwfpe/fpa11.c                |    2 
 linux-user/arm/nwfpe/fpa11.h                |    2 
 linux-user/arm/nwfpe/fpa11_cpdt.c           |    8 
 linux-user/arm/nwfpe/fpa11_cprt.c           |    2 
 linux-user/elfload.c                        |  108 +
 linux-user/ioctls.h                         |    4 
 linux-user/main.c                           |   91 +
 linux-user/mmap.c                           |    4 
 linux-user/qemu.h                           |    5 
 linux-user/strace.c                         |  252 ++
 linux-user/strace.list                      |   15 
 linux-user/syscall.c                        |  281 +++
 linux-user/syscall_defs.h                   |   31 
 linux-user/unicore32/syscall.h              |   55 
 linux-user/unicore32/syscall_nr.h           |  371 ++++
 linux-user/unicore32/target_signal.h        |   26 
 linux-user/unicore32/termbits.h             |    2 
 migration-exec.c                            |    1 
 migration-fd.c                              |    1 
 migration-tcp.c                             |    5 
 migration-unix.c                            |    5 
 migration.c                                 |    2 
 migration.h                                 |    9 
 monitor.c                                   |  104 -
 nbd.c                                       |  993 +++++------
 nbd.h                                       |    9 
 net-checksum.c                              |   86 -
 net.c                                       |  127 -
 net/dump.c                                  |    4 
 net/slirp.c                                 |    1 
 net/socket.c                                |    2 
 net/tap-win32.c                             |    2 
 net/vde.c                                   |    1 
 os-posix.c                                  |   26 
 os-win32.c                                  |    9 
 osdep.c                                     |    1 
 osdep.h                                     |   24 
 oslib-win32.c                               |    7 
 pc-bios/README                              |   20 
 pc-bios/bios.bin                            |binary
 pc-bios/linuxboot.bin                       |binary
 pc-bios/multiboot.bin                       |binary
 pc-bios/optionrom/linuxboot.S               |    2 
 pc-bios/optionrom/multiboot.S               |    2 
 pc-bios/optionrom/optionrom.h               |   40 
 pc-bios/petalogix-ml605.dtb                 |binary
 pc-bios/pxe-e1000.rom                       |binary
 pc-bios/pxe-eepro100.rom                    |binary
 pc-bios/pxe-ne2k_pci.rom                    |binary
 pc-bios/pxe-pcnet.rom                       |binary
 pc-bios/pxe-rtl8139.rom                     |binary
 pc-bios/pxe-virtio.rom                      |binary
 pc-bios/slof.bin                            |binary
 pc-bios/spapr-rtas.bin                      |binary
 pc-bios/spapr-rtas/Makefile                 |   24 
 pc-bios/spapr-rtas/spapr-rtas.S             |   37 
 poison.h                                    |    1 
 posix-aio-compat.c                          |    5 
 qemu-char.c                                 |   21 
 qemu-char.h                                 |    1 
 qemu-common.h                               |   40 
 qemu-config.c                               |    1 
 qemu-error.c                                |    1 
 qemu-img-cmds.hx                            |    4 
 qemu-img.c                                  |   56 
 qemu-lock.h                                 |  210 --
 qemu-options.hx                             |   56 
 qemu-os-win32.h                             |    3 
 qemu-progress.c                             |   89 +
 qemu-sockets.c                              |    4 
 qemu-thread-posix.c                         |  149 +
 qemu-thread-posix.h                         |   17 
 qemu-thread-win32.c                         |  281 +++
 qemu-thread-win32.h                         |   21 
 qemu-thread.c                               |  192 --
 qemu-thread.h                               |   33 
 qemu-timer.c                                |  269 +--
 qemu-timer.h                                |   34 
 qemu-tool.c                                 |   48 
 qemu_socket.h                               |    3 
 qerror.c                                    |    5 
 qerror.h                                    |    6 
 qmp-commands.hx                             |   71 
 roms/SLOF                                   |    1 
 roms/ipxe                                   |    1 
 roms/seabios                                |    2 
 savevm.c                                    |   42 
 scripts/refresh-pxe-roms.sh                 |   99 +
 scripts/simpletrace.py                      |  126 +
 scripts/tracetool                           |   26 
 simpletrace.c                               |  308 ++-
 simpletrace.h                               |    8 
 slirp/bootp.c                               |    2 
 slirp/misc.c                                |    5 
 slirp/slirp.c                               |    2 
 slirp/tftp.c                                |   14 
 slirp/tftp.h                                |    2 
 sysemu.h                                    |   49 
 target-alpha/exec.h                         |   11 
 target-alpha/op_helper.c                    |   11 
 target-alpha/translate.c                    |    9 
 target-arm/cpu.h                            |   10 
 target-arm/exec.h                           |   13 
 target-arm/helper.c                         |  495 ++++-
 target-arm/helper.h                         |  475 +++++
 target-arm/helpers.h                        |  463 -----
 target-arm/iwmmxt_helper.c                  |   82 
 target-arm/machine.c                        |    2 
 target-arm/neon_helper.c                    |  693 ++++++--
 target-arm/op_helper.c                      |    4 
 target-arm/translate.c                      | 2356 ++++++++++++++++------------
 target-cris/exec.h                          |   11 
 target-cris/op_helper.c                     |    2 
 target-cris/translate.c                     |    5 
 target-i386/cpu.h                           |   14 
 target-i386/cpuid.c                         |    1 
 target-i386/exec.h                          |   80 
 target-i386/helper.c                        |  202 +-
 target-i386/kvm.c                           |  699 +++-----
 target-i386/kvm_x86.h                       |   25 
 target-i386/op_helper.c                     |  225 +-
 target-i386/ops_sse.h                       |   48 
 target-i386/translate.c                     |    9 
 target-lm32/README                          |   46 
 target-lm32/TODO                            |    3 
 target-lm32/cpu.h                           |  244 ++
 target-lm32/exec.h                          |   50 
 target-lm32/helper.c                        |  259 +++
 target-lm32/helper.h                        |   14 
 target-lm32/machine.c                       |   33 
 target-lm32/op_helper.c                     |  106 +
 target-lm32/translate.c                     | 1272 +++++++++++++++
 target-m68k/exec.h                          |   10 
 target-m68k/op_helper.c                     |    2 
 target-m68k/translate.c                     |    5 
 target-microblaze/cpu.h                     |   16 
 target-microblaze/exec.h                    |   11 
 target-microblaze/helper.h                  |    3 
 target-microblaze/microblaze-decode.h       |    3 
 target-microblaze/op_helper.c               |   41 
 target-microblaze/translate.c               |   44 
 target-mips/cpu.h                           |    2 
 target-mips/exec.h                          |   11 
 target-mips/op_helper.c                     |  248 +-
 target-mips/translate.c                     |    5 
 target-ppc/cpu.h                            |   84 
 target-ppc/exec.h                           |   11 
 target-ppc/helper.c                         |  449 ++---
 target-ppc/helper.h                         |    7 
 target-ppc/kvm.c                            |   32 
 target-ppc/kvm_ppc.c                        |    6 
 target-ppc/kvm_ppc.h                        |   20 
 target-ppc/machine.c                        |    6 
 target-ppc/op_helper.c                      |  123 -
 target-ppc/translate.c                      |  268 ++-
 target-ppc/translate_init.c                 |  164 +
 target-s390x/cpu.h                          |  774 ++++++++-
 target-s390x/exec.h                         |   17 
 target-s390x/helper.c                       |    4 
 target-s390x/kvm.c                          |   43 
 target-s390x/op_helper.c                    |    2 
 target-s390x/translate.c                    |    5 
 target-sh4/cpu.h                            |    2 
 target-sh4/exec.h                           |   11 
 target-sh4/helper.c                         |    4 
 target-sh4/helper.h                         |   48 
 target-sh4/op_helper.c                      |  205 --
 target-sh4/translate.c                      |    5 
 target-sparc/exec.h                         |   10 
 target-sparc/op_helper.c                    |    2 
 target-sparc/translate.c                    |    5 
 target-unicore32/cpu.h                      |  182 ++
 target-unicore32/exec.h                     |   50 
 target-unicore32/helper.c                   |  487 +++++
 target-unicore32/helper.h                   |   70 
 target-unicore32/op_helper.c                |  248 ++
 target-unicore32/translate.c                | 2104 +++++++++++++++++++++++++
 tcg/arm/tcg-target.c                        |   35 
 tcg/tcg.c                                   |   32 
 tcg/tcg.h                                   |   17 
 tests/Makefile                              |    4 
 tests/cris/check_openpf1.c                  |    2 
 tests/cris/check_openpf2.c                  |    2 
 tests/cris/check_stat3.c                    |    2 
 tests/cris/check_stat4.c                    |    2 
 tests/linux-test.c                          |    2 
 tests/lm32/Makefile                         |  102 +
 tests/lm32/crt.S                            |   84 
 tests/lm32/linker.ld                        |   55 
 tests/lm32/macros.inc                       |   79 
 tests/lm32/test_add.S                       |   75 
 tests/lm32/test_addi.S                      |   56 
 tests/lm32/test_and.S                       |   45 
 tests/lm32/test_andhi.S                     |   35 
 tests/lm32/test_andi.S                      |   35 
 tests/lm32/test_b.S                         |   13 
 tests/lm32/test_be.S                        |   48 
 tests/lm32/test_bg.S                        |   78 
 tests/lm32/test_bge.S                       |   78 
 tests/lm32/test_bgeu.S                      |   78 
 tests/lm32/test_bgu.S                       |   78 
 tests/lm32/test_bi.S                        |   23 
 tests/lm32/test_bne.S                       |   48 
 tests/lm32/test_break.S                     |   20 
 tests/lm32/test_bret.S                      |   38 
 tests/lm32/test_call.S                      |   16 
 tests/lm32/test_calli.S                     |   15 
 tests/lm32/test_cmpe.S                      |   40 
 tests/lm32/test_cmpei.S                     |   35 
 tests/lm32/test_cmpg.S                      |   64 
 tests/lm32/test_cmpge.S                     |   64 
 tests/lm32/test_cmpgei.S                    |   55 
 tests/lm32/test_cmpgeu.S                    |   64 
 tests/lm32/test_cmpgeui.S                   |   55 
 tests/lm32/test_cmpgi.S                     |   55 
 tests/lm32/test_cmpgu.S                     |   64 
 tests/lm32/test_cmpgui.S                    |   55 
 tests/lm32/test_cmpne.S                     |   40 
 tests/lm32/test_cmpnei.S                    |   35 
 tests/lm32/test_divu.S                      |   29 
 tests/lm32/test_eret.S                      |   38 
 tests/lm32/test_lb.S                        |   45 
 tests/lm32/test_lbu.S                       |   45 
 tests/lm32/test_lh.S                        |   45 
 tests/lm32/test_lhu.S                       |   45 
 tests/lm32/test_lw.S                        |   30 
 tests/lm32/test_modu.S                      |   35 
 tests/lm32/test_mul.S                       |   70 
 tests/lm32/test_muli.S                      |   45 
 tests/lm32/test_nor.S                       |   51 
 tests/lm32/test_nori.S                      |   35 
 tests/lm32/test_or.S                        |   51 
 tests/lm32/test_orhi.S                      |   35 
 tests/lm32/test_ori.S                       |   35 
 tests/lm32/test_ret.S                       |   14 
 tests/lm32/test_sb.S                        |   30 
 tests/lm32/test_scall.S                     |   20 
 tests/lm32/test_sextb.S                     |   20 
 tests/lm32/test_sexth.S                     |   20 
 tests/lm32/test_sh.S                        |   30 
 tests/lm32/test_sl.S                        |   45 
 tests/lm32/test_sli.S                       |   30 
 tests/lm32/test_sr.S                        |   57 
 tests/lm32/test_sri.S                       |   40 
 tests/lm32/test_sru.S                       |   57 
 tests/lm32/test_srui.S                      |   40 
 tests/lm32/test_sub.S                       |   75 
 tests/lm32/test_sw.S                        |   35 
 tests/lm32/test_xnor.S                      |   51 
 tests/lm32/test_xnori.S                     |   35 
 tests/lm32/test_xor.S                       |   51 
 tests/lm32/test_xori.S                      |   35 
 tests/test-mmap.c                           |    2 
 trace-events                                |  120 +
 translate-all.c                             |    5 
 ui/sdl.c                                    |   33 
 ui/spice-core.c                             |    4 
 ui/vnc-enc-tight.c                          |   84 
 ui/vnc-enc-zlib.c                           |    4 
 ui/vnc-enc-zrle-template.c                  |  263 +++
 ui/vnc-enc-zrle.c                           |  366 ++++
 ui/vnc-enc-zrle.h                           |   40 
 ui/vnc-enc-zywrle-template.c                |  170 ++
 ui/vnc-enc-zywrle.h                         |  659 +++++++
 ui/vnc-jobs-async.c                         |    8 
 ui/vnc-palette.c                            |   58 
 ui/vnc-palette.h                            |    7 
 ui/vnc.c                                    |  310 ++-
 ui/vnc.h                                    |   60 
 ui/vnc_keysym.h                             |   18 
 usb-bsd.c                                   |    2 
 usb-linux.c                                 |    9 
 vl.c                                        |  377 ++--
 638 files changed, 49991 insertions(+), 10318 deletions(-)

New commits:
commit 430a3c18064fd3c007048d757e8bd0fff45fcc99
Author: Michael Walle <michael at walle.cc>
Date:   Tue Apr 26 00:09:01 2011 +0200

    configure: reenable opengl by default
    
    Because the opengl library is only linked to for the lm32 target, we can
    now safely enable opengl by default again.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 2c95796..35f7e8b 100755
--- a/configure
+++ b/configure
@@ -177,7 +177,7 @@ spice=""
 rbd=""
 smartcard=""
 smartcard_nss=""
-opengl="no"
+opengl=""
 
 # parse CC options first
 for opt do
commit de3a354a8323296f200a76c0de5984c4d14c0a9e
Author: Michael Walle <michael at walle.cc>
Date:   Tue Apr 26 00:24:07 2011 +0200

    configure: support target dependent linking
    
    This patch is the first attempt to make configure more intelligent with
    regard to how it links to libraries. It divides the softmmu libraries into
    two lists, a general one and a list which depends on the target
    architecture.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 2bbbbf5..2c95796 100755
--- a/configure
+++ b/configure
@@ -1946,11 +1946,11 @@ int main(void) { return 0; }
 EOF
   if compile_prog "" "$fdt_libs" ; then
     fdt=yes
-    libs_softmmu="$fdt_libs $libs_softmmu"
   else
     if test "$fdt" = "yes" ; then
       feature_not_found "fdt"
     fi
+    fdt_libs=
     fdt=no
   fi
 fi
@@ -1967,11 +1967,11 @@ int main(void) { GL_VERSION; return 0; }
 EOF
   if compile_prog "" "-lGL" ; then
     opengl=yes
-       libs_softmmu="$opengl_libs $libs_softmmu"
   else
     if test "$opengl" = "yes" ; then
       feature_not_found "opengl"
     fi
+    opengl_libs=
     opengl=no
   fi
 fi
@@ -3079,6 +3079,7 @@ target_short_alignment=2
 target_int_alignment=4
 target_long_alignment=4
 target_llong_alignment=8
+target_libs_softmmu=
 
 TARGET_ARCH="$target_arch2"
 TARGET_BASE_ARCH=""
@@ -3112,6 +3113,7 @@ case "$target_arch2" in
   ;;
   lm32)
     target_phys_bits=32
+    target_libs_softmmu="$opengl_libs"
   ;;
   m68k)
     bflt="yes"
@@ -3126,6 +3128,7 @@ case "$target_arch2" in
     bflt="yes"
     target_nptl="yes"
     target_phys_bits=32
+    target_libs_softmmu="$fdt_libs"
   ;;
   mips|mipsel)
     TARGET_ARCH=mips
@@ -3150,6 +3153,7 @@ case "$target_arch2" in
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=32
     target_nptl="yes"
+    target_libs_softmmu="$fdt_libs"
   ;;
   ppcemb)
     TARGET_BASE_ARCH=ppc
@@ -3157,6 +3161,7 @@ case "$target_arch2" in
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=64
     target_nptl="yes"
+    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64)
     TARGET_BASE_ARCH=ppc
@@ -3164,6 +3169,7 @@ case "$target_arch2" in
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=64
     target_long_alignment=8
+    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64abi32)
     TARGET_ARCH=ppc64
@@ -3172,6 +3178,7 @@ case "$target_arch2" in
     echo "TARGET_ABI32=y" >> $config_target_mak
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=64
+    target_libs_softmmu="$fdt_libs"
   ;;
   sh4|sh4eb)
     TARGET_ARCH=sh4
@@ -3257,7 +3264,7 @@ fi
 if test "$target_softmmu" = "yes" ; then
   echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
   echo "CONFIG_SOFTMMU=y" >> $config_target_mak
-  echo "LIBS+=$libs_softmmu" >> $config_target_mak
+  echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak
   echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak
   echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak
 fi
commit 1a924df6206c089cd4925479dbc0cb9667019b35
Merge: 19e83f6... 0c866a7...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Apr 26 23:23:02 2011 +0200

    Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
    
    * 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
      linux-user: untie syscalls from UID16
      linux-user: add s390x to llseek list
      linux-user: add ioctl(SIOCGIWNAME, ...) support.
      linux-user: convert ioctl(SIOCGIFCONF, ...) result.
      linux-user: improve traces
      [v2] linux-user: bigger default stack

commit 19e83f6bdf86f92ee90db77d606affe5b08f8b40
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 26 16:56:40 2011 +0100

    configure: Make epoll_create1 test work around SPARC glibc bug
    
    Work around a SPARC glibc bug which caused the epoll_create1 configure
    test to wrongly claim that the function was present. Some versions of
    SPARC glibc provided the function in the library but didn't declare
    it in the include file; the result is that gcc warns about an implicit
    declaration but a link succeeds. So we reference the function as a
    value rather than a function call to induce a compile time error
    if the declaration was not present.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index de44bac..2bbbbf5 100755
--- a/configure
+++ b/configure
@@ -2225,7 +2225,15 @@ cat > $TMPC << EOF
 
 int main(void)
 {
-    epoll_create1(0);
+    /* Note that we use epoll_create1 as a value, not as
+     * a function being called. This is necessary so that on
+     * old SPARC glibc versions where the function was present in
+     * the library but not declared in the header file we will
+     * fail the configure check. (Otherwise we will get a compiler
+     * warning but not an error, and will proceed to fail the
+     * qemu compile where we compile with -Werror.)
+     */
+    epoll_create1;
     return 0;
 }
 EOF
commit 143f6ffe9cd288d2b507ddc1508316181c1007a7
Merge: 71785ab... 2b287af...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 26 08:07:49 2011 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging

commit 71785abaea26e185f7dc19ab376c0ed51d469d90
Author: Brad Hards <bradh at frogmouth.net>
Date:   Sat Apr 23 21:50:06 2011 +1000

    vl: trivial spelling fix
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/vl.c b/vl.c
index 68c3b53..b46ee66 100644
--- a/vl.c
+++ b/vl.c
@@ -756,7 +756,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
 
 /*
  * This function returns null terminated string that consist of new line
- * separated device pathes.
+ * separated device paths.
  *
  * memory pointed by "size" is assigned total length of the array in bytes
  *
commit 2b287af620ac634a156a1c4dd68e937aacbcb144
Author: Lluís <xscript at gmx.net>
Date:   Wed Apr 6 20:34:11 2011 +0200

    trace: [trace-events] fix print formats in some events
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/trace-events b/trace-events
index 8272c86..77c96a5 100644
--- a/trace-events
+++ b/trace-events
@@ -254,8 +254,8 @@ disable leon3_set_irq(int intno) "Set CPU IRQ %d"
 disable leon3_reset_irq(int intno) "Reset CPU IRQ %d"
 
 # spice-qemu-char.c
-disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
-disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+disable spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d"
+disable spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
 disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
 disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
 
commit fa2d480a20345b8f10881712dbcf3f5f48b5905b
Author: Lluís <xscript at gmx.net>
Date:   Wed Apr 6 20:34:03 2011 +0200

    trace: [ust] fix generation of 'trace.c' on events without args
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index 9912f36..2155a57 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -338,6 +338,7 @@ linetoc_ust()
     name=$(get_name "$1")
     args=$(get_args "$1")
     argnames=$(get_argnames "$1", ",")
+    [ -z "$argnames" ] || argnames=", $argnames"
     fmt=$(get_fmt "$1")
 
     cat <<EOF
@@ -345,7 +346,7 @@ DEFINE_TRACE(ust_$name);
 
 static void ust_${name}_probe($args)
 {
-    trace_mark(ust, $name, "$fmt", $argnames);
+    trace_mark(ust, $name, "$fmt"$argnames);
 }
 EOF
 
@@ -488,7 +489,7 @@ EOF
         cat <<EOF
   $arg = \$arg$i;
 EOF
-	i="$((i+1))"
+        i="$((i+1))"
     done
 
     cat <<EOF
@@ -585,7 +586,7 @@ tracetostap()
        exit 1
     fi
     if [ -z "$probeprefix" ]; then
-	probeprefix="qemu.$targettype.$targetarch";
+        probeprefix="qemu.$targettype.$targetarch";
     fi
     echo "/* This file is autogenerated by tracetool, do not edit. */"
     convert stap
commit 7b92e5bc6d7a61e9e7669b679a87480a6d1ad1a6
Author: Lluís <xscript at gmx.net>
Date:   Wed Apr 6 20:33:56 2011 +0200

    docs/tracing.txt: minor documentation fixes
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 905a083..c99a0f2 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -26,14 +26,14 @@ for debugging, profiling, and observing execution.
 
 == Trace events ==
 
-There is a set of static trace events declared in the trace-events source
+There is a set of static trace events declared in the "trace-events" source
 file.  Each trace event declaration names the event, its arguments, and the
 format string which can be used for pretty-printing:
 
     qemu_malloc(size_t size, void *ptr) "size %zu ptr %p"
     qemu_free(void *ptr) "ptr %p"
 
-The trace-events file is processed by the tracetool script during build to
+The "trace-events" file is processed by the "tracetool" script during build to
 generate code for the trace events.  Trace events are invoked directly from
 source code like this:
 
@@ -52,10 +52,10 @@ source code like this:
 
 === Declaring trace events ===
 
-The tracetool script produces the trace.h header file which is included by
+The "tracetool" script produces the trace.h header file which is included by
 every source file that uses trace events.  Since many source files include
-trace.h, it uses a minimum of types and other header files included to keep
-the namespace clean and compile times and dependencies down.
+trace.h, it uses a minimum of types and other header files included to keep the
+namespace clean and compile times and dependencies down.
 
 Trace events should use types as follows:
 
@@ -110,10 +110,10 @@ portability macros, ensure they are preceded and followed by double quotes:
 
 == Trace backends ==
 
-The tracetool script automates tedious trace event code generation and also
+The "tracetool" script automates tedious trace event code generation and also
 keeps the trace event declarations independent of the trace backend.  The trace
 events are not tightly coupled to a specific trace backend, such as LTTng or
-SystemTap.  Support for trace backends can be added by extending the tracetool
+SystemTap.  Support for trace backends can be added by extending the "tracetool"
 script.
 
 The trace backend is chosen at configure time and only one trace backend can
@@ -181,12 +181,12 @@ events at runtime inside QEMU:
 ==== Analyzing trace files ====
 
 The "simple" backend produces binary trace files that can be formatted with the
-simpletrace.py script.  The script takes the trace-events file and the binary
+simpletrace.py script.  The script takes the "trace-events" file and the binary
 trace:
 
     ./simpletrace.py trace-events trace-12345
 
-You must ensure that the same trace-events file was used to build QEMU,
+You must ensure that the same "trace-events" file was used to build QEMU,
 otherwise trace event declarations may have changed and output will not be
 consistent.
 
commit e6a750aab57e4dccefd6291dba4fee6b9b3bf9ee
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Apr 14 18:24:50 2011 +0100

    docs: Trace events must not expect pointer dereferencing
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index f15069c..905a083 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -69,6 +69,11 @@ Trace events should use types as follows:
    cannot include all user-defined struct declarations and it is therefore
    necessary to use void * for pointers to structs.
 
+   Pointers (including char *) cannot be dereferenced easily (or at all) in
+   some trace backends.  If pointers are used, ensure they are meaningful by
+   themselves and do not assume the data they point to will be traced.  Do
+   not pass in string arguments.
+
  * For everything else, use primitive scalar types (char, int, long) with the
    appropriate signedness.
 
commit b4548fcc0314f5e118ed45b5774e9cd99f9a97d3
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Apr 14 18:11:00 2011 +0100

    trace: Remove %s in grlib trace events
    
    Trace events cannot use %s in their format strings because trace
    backends vary in how they can deference pointers (if at all).  Recording
    const char * values is not meaningful if their contents are not recorded
    too.
    
    Change grlib trace events that rely on strings so that they communicate
    similar information without using strings.
    
    A follow-up patch explains this limitation and updates docs/tracing.txt.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index 101b150..169a56e 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -133,7 +133,7 @@ grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
         break;
     }
 
-    trace_grlib_apbuart_unknown_register("write", addr);
+    trace_grlib_apbuart_writel_unknown(addr, value);
 }
 
 static CPUReadMemoryFunc * const grlib_apbuart_read[] = {
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 596a900..99e9033 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -165,15 +165,15 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
     /* Unit registers */
     switch (addr) {
     case SCALER_OFFSET:
-        trace_grlib_gptimer_readl(-1, "scaler:", unit->scaler);
+        trace_grlib_gptimer_readl(-1, addr, unit->scaler);
         return unit->scaler;
 
     case SCALER_RELOAD_OFFSET:
-        trace_grlib_gptimer_readl(-1, "reload:", unit->reload);
+        trace_grlib_gptimer_readl(-1, addr, unit->reload);
         return unit->reload;
 
     case CONFIG_OFFSET:
-        trace_grlib_gptimer_readl(-1, "config:", unit->config);
+        trace_grlib_gptimer_readl(-1, addr, unit->config);
         return unit->config;
 
     default:
@@ -189,17 +189,16 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
         switch (timer_addr) {
         case COUNTER_OFFSET:
             value = ptimer_get_count(unit->timers[id].ptimer);
-            trace_grlib_gptimer_readl(id, "counter value:", value);
+            trace_grlib_gptimer_readl(id, addr, value);
             return value;
 
         case COUNTER_RELOAD_OFFSET:
             value = unit->timers[id].reload;
-            trace_grlib_gptimer_readl(id, "reload value:", value);
+            trace_grlib_gptimer_readl(id, addr, value);
             return value;
 
         case CONFIG_OFFSET:
-            trace_grlib_gptimer_readl(id, "scaler value:",
-                                      unit->timers[id].config);
+            trace_grlib_gptimer_readl(id, addr, unit->timers[id].config);
             return unit->timers[id].config;
 
         default:
@@ -208,7 +207,7 @@ static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
 
     }
 
-    trace_grlib_gptimer_unknown_register("read", addr);
+    trace_grlib_gptimer_readl(-1, addr, 0);
     return 0;
 }
 
@@ -226,19 +225,19 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
     case SCALER_OFFSET:
         value &= 0xFFFF; /* clean up the value */
         unit->scaler = value;
-        trace_grlib_gptimer_writel(-1, "scaler:", unit->scaler);
+        trace_grlib_gptimer_writel(-1, addr, unit->scaler);
         return;
 
     case SCALER_RELOAD_OFFSET:
         value &= 0xFFFF; /* clean up the value */
         unit->reload = value;
-        trace_grlib_gptimer_writel(-1, "reload:", unit->reload);
+        trace_grlib_gptimer_writel(-1, addr, unit->reload);
         grlib_gptimer_set_scaler(unit, value);
         return;
 
     case CONFIG_OFFSET:
         /* Read Only (disable timer freeze not supported) */
-        trace_grlib_gptimer_writel(-1, "config (Read Only):", 0);
+        trace_grlib_gptimer_writel(-1, addr, 0);
         return;
 
     default:
@@ -253,18 +252,18 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
         /* GPTimer registers */
         switch (timer_addr) {
         case COUNTER_OFFSET:
-            trace_grlib_gptimer_writel(id, "counter:", value);
+            trace_grlib_gptimer_writel(id, addr, value);
             unit->timers[id].counter = value;
             grlib_gptimer_enable(&unit->timers[id]);
             return;
 
         case COUNTER_RELOAD_OFFSET:
-            trace_grlib_gptimer_writel(id, "reload:", value);
+            trace_grlib_gptimer_writel(id, addr, value);
             unit->timers[id].reload = value;
             return;
 
         case CONFIG_OFFSET:
-            trace_grlib_gptimer_writel(id, "config:", value);
+            trace_grlib_gptimer_writel(id, addr, value);
 
             if (value & GPTIMER_INT_PENDING) {
                 /* clear pending bit */
@@ -297,7 +296,7 @@ grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
 
     }
 
-    trace_grlib_gptimer_unknown_register("write", addr);
+    trace_grlib_gptimer_writel(-1, addr, value);
 }
 
 static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index f47c491..b8738fc 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -220,7 +220,7 @@ static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
         return state->extended[cpu];
     }
 
-    trace_grlib_irqmp_unknown_register("read", addr);
+    trace_grlib_irqmp_readl_unknown(addr);
     return 0;
 }
 
@@ -308,7 +308,7 @@ grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
         return;
     }
 
-    trace_grlib_irqmp_unknown_register("write", addr);
+    trace_grlib_irqmp_writel_unknown(addr, value);
 }
 
 static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
diff --git a/trace-events b/trace-events
index 703b745..8272c86 100644
--- a/trace-events
+++ b/trace-events
@@ -235,19 +235,19 @@ disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable
 disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
 disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
 disable grlib_gptimer_hit(int id) "timer:%d HIT"
-disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
-disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
-disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
+disable grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
 
 # hw/grlib_irqmp.c
 disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n"
 disable grlib_irqmp_ack(int intno) "interrupt:%d"
 disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
-disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64""
+disable grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
 
 # hw/grlib_apbuart.c
 disable grlib_apbuart_event(int event) "event:%d"
-disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+disable grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
 
 # hw/leon3.c
 disable leon3_set_irq(int intno) "Set CPU IRQ %d"
commit 1a96dd472c37ceeefc0d488cb7722c6714d2f0b7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Apr 15 15:23:59 2011 +0200

    tracetool: allow ) in trace output string
    
    Be greedy in matching the trailing "\)*" pattern.  Otherwise, all the
    text in the trace string up to the last closed parenthesis is taken as
    part of the prototype.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/scripts/tracetool b/scripts/tracetool
index 412f695..9912f36 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -51,7 +51,7 @@ get_args()
 {
     local args
     args=${1#*\(}
-    args=${args%\)*}
+    args=${args%%\)*}
     echo "$args"
 }
 
commit 0c866a7ed47bc8a2df320e59bc669e4784d8ad2f
Author: Riku Voipio <riku.voipio at iki.fi>
Date:   Mon Apr 18 15:23:06 2011 +0300

    linux-user: untie syscalls from UID16
    
    Quite a number of uid/gid related syscalls are only defined on systems
    with USE_UID16 defined. This is apperently based on the idea that these
    system calls would never be called on non-UID16 systems. Make these
    syscalls available for all architectures that define them.
    
    drop alpha hack to support selected UID16 syscalls. MIPS and PowerPC
    were also defined as UID16, to get uid/gid syscalls available, drop
    this error as well.
    
    Change QEMU to reflect this.
    
    Cc: Ulrich Hecht <uli at suse.de>
    Cc: Richard Henderson <rth at twiddle.net>
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h
index 7182223..e3127df 100644
--- a/linux-user/alpha/syscall_nr.h
+++ b/linux-user/alpha/syscall_nr.h
@@ -412,10 +412,3 @@
 #define TARGET_NR_timerfd			477
 #define TARGET_NR_eventfd			478
 
-/* The following aliases are defined in order to match up with the
-   standard i386 syscalls implemented in syscalls.c.  */
-#define TARGET_NR_chown32	TARGET_NR_chown
-#define TARGET_NR_setuid32	TARGET_NR_setuid
-#define TARGET_NR_setgid32	TARGET_NR_setgid
-#define TARGET_NR_setfsuid32	TARGET_NR_setfsuid
-#define TARGET_NR_setfsgid32	TARGET_NR_setfsgid
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e7af2ea..e969d1b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -328,7 +328,7 @@ static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
   return (fchmodat(dirfd, pathname, mode, 0));
 }
 #endif
-#if defined(TARGET_NR_fchownat) && defined(USE_UID16)
+#if defined(TARGET_NR_fchownat)
 static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
     gid_t group, int flags)
 {
@@ -437,7 +437,7 @@ _syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
 #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
 _syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
 #endif
-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
 _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
           uid_t,owner,gid_t,group,int,flags)
 #endif
@@ -4164,7 +4164,31 @@ static inline int low2highgid(int gid)
     else
         return gid;
 }
-
+static inline int tswapid(int id)
+{
+    return tswap16(id);
+}
+#else /* !USE_UID16 */
+static inline int high2lowuid(int uid)
+{
+    return uid;
+}
+static inline int high2lowgid(int gid)
+{
+    return gid;
+}
+static inline int low2highuid(int uid)
+{
+    return uid;
+}
+static inline int low2highgid(int gid)
+{
+    return gid;
+}
+static inline int tswapid(int id)
+{
+    return tswap32(id);
+}
 #endif /* USE_UID16 */
 
 void syscall_init(void)
@@ -6765,25 +6789,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             ret = host_to_target_stat64(cpu_env, arg3, &st);
         break;
 #endif
-#ifdef USE_UID16
     case TARGET_NR_lchown:
         if (!(p = lock_user_string(arg1)))
             goto efault;
         ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
         unlock_user(p, arg1, 0);
         break;
+#ifdef TARGET_NR_getuid
     case TARGET_NR_getuid:
         ret = get_errno(high2lowuid(getuid()));
         break;
+#endif
+#ifdef TARGET_NR_getgid
     case TARGET_NR_getgid:
         ret = get_errno(high2lowgid(getgid()));
         break;
+#endif
+#ifdef TARGET_NR_geteuid
     case TARGET_NR_geteuid:
         ret = get_errno(high2lowuid(geteuid()));
         break;
+#endif
+#ifdef TARGET_NR_getegid
     case TARGET_NR_getegid:
         ret = get_errno(high2lowgid(getegid()));
         break;
+#endif
     case TARGET_NR_setreuid:
         ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
         break;
@@ -6793,7 +6824,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_getgroups:
         {
             int gidsetsize = arg1;
-            uint16_t *target_grouplist;
+            target_id *target_grouplist;
             gid_t *grouplist;
             int i;
 
@@ -6806,7 +6837,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 if (!target_grouplist)
                     goto efault;
                 for(i = 0;i < ret; i++)
-                    target_grouplist[i] = tswap16(grouplist[i]);
+                    target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
                 unlock_user(target_grouplist, arg2, gidsetsize * 2);
             }
         }
@@ -6814,7 +6845,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_setgroups:
         {
             int gidsetsize = arg1;
-            uint16_t *target_grouplist;
+            target_id *target_grouplist;
             gid_t *grouplist;
             int i;
 
@@ -6825,7 +6856,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 goto fail;
             }
             for(i = 0;i < gidsetsize; i++)
-                grouplist[i] = tswap16(target_grouplist[i]);
+                grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
             unlock_user(target_grouplist, arg2, 0);
             ret = get_errno(setgroups(gidsetsize, grouplist));
         }
@@ -6901,7 +6932,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_setfsgid:
         ret = get_errno(setfsgid(arg1));
         break;
-#endif /* USE_UID16 */
 
 #ifdef TARGET_NR_lchown32
     case TARGET_NR_lchown32:
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 527f31d..e05ddf9 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -49,9 +49,12 @@
 #define TARGET_IOC_TYPEBITS	8
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
-    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) || defined(TARGET_PPC) || defined(TARGET_MIPS)
+    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
     /* 16 bit uid wrappers emulation */
 #define USE_UID16
+#define target_id uint16_t
+#else
+#define target_id uint32_t
 #endif
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
commit 42a39fbe0cb6549e9cedfe63e706fdf951126626
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 15 17:32:45 2011 +0200

    linux-user: add s390x to llseek list
    
    We keep a list of host architectures that do llseek with the same
    syscall as lseek. S390x is one of them, so let's add it to the list.
    
    Original-patch-by: Ulrich Hecht <uli at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5f9061d..e7af2ea 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -197,7 +197,8 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\
 #define __NR_sys_inotify_add_watch __NR_inotify_add_watch
 #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
 
-#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
+    defined(__s390x__)
 #define __NR__llseek __NR_lseek
 #endif
 
commit 86fcd9463240c256f00963440fbd084196eeb964
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Wed Mar 30 01:35:23 2011 +0200

    linux-user: add ioctl(SIOCGIWNAME, ...) support.
    
    Allow to run properly following program from linux-user:
    
    /* cc -o wifi wifi.c */
    
     #include <stdio.h>
     #include <sys/ioctl.h>
     #include <sys/types.h>
     #include <sys/socket.h>
     #include <linux/wireless.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
     #include <string.h>
    
    int main(int argc, char **argv)
    {
        int ret;
        struct ifreq req;
        struct sockaddr_in *addr;
        int s;
    
        if (argc != 2) {
            fprintf(stderr, "Need an interface name (like wlan0)\n");
    	return 1;
        }
    
        s = socket( AF_INET, SOCK_DGRAM, 0 );
        if (s < 0) {
            perror("Cannot open socket");
            return 1;
        }
        strncpy(req.ifr_name, argv[1], sizeof(req.ifr_name));
        ret = ioctl( s, SIOCGIWNAME, &req );
        if (ret < 0) {
    	fprintf(stderr, "No wireless extension\n");
            return 1;
        }
    
        printf("%s\n", req.ifr_name);
        printf("%s\n", req.ifr_newname);
        return 0;
    }
    
    $ ./wifi eth0
    No wireless extension
    
    $ ./wifi wlan0
    wlan0
    IEEE 802.11bg
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index ab15b86..42b3ae3 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -122,6 +122,7 @@
   IOCTL(SIOCDRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
   IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
   IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
+  IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
 
   IOCTL(CDROMPAUSE, 0, TYPE_NULL)
   IOCTL(CDROMSTART, 0, TYPE_NULL)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 123909f..5f9061d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -59,7 +59,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 //#include <sys/user.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
-#include <net/if.h>
+#include <linux/wireless.h>
 #include <qemu-common.h>
 #ifdef TARGET_GPROF
 #include <sys/gmon.h>
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index bde8921..527f31d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -765,6 +765,9 @@ struct target_pollfd {
 #define TARGET_SIOCADDDLCI     0x8980          /* Create new DLCI device       */
 #define TARGET_SIOCDELDLCI     0x8981          /* Delete DLCI device           */
 
+/* From <linux/wireless.h> */
+
+#define TARGET_SIOCGIWNAME     0x8B01          /* get name == wireless protocol */
 
 /* From <linux/fs.h> */
 
commit 059c2f2cd773e0f3d7284a6eab662fd26f9cbad2
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Wed Mar 30 00:12:12 2011 +0200

    linux-user: convert ioctl(SIOCGIFCONF, ...) result.
    
    The result needs to be converted as it is stored in an array of struct
    ifreq and sizeof(struct ifreq) differs according to target and host
    alignment rules.
    
    This patch allows to execute correctly the following program on arm
    and m68k:
    
     #include <stdio.h>
     #include <sys/ioctl.h>
     #include <net/if.h>
     #include <alloca.h>
     #include <string.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
    
    int main(void)
    {
        int s, ret;
        struct ifconf ifc;
        int i;
    
        memset( &ifc, 0, sizeof( struct ifconf ) );
        ifc.ifc_len = 8 * sizeof(struct ifreq);
        ifc.ifc_buf = alloca(ifc.ifc_len);
    
        s = socket( AF_INET, SOCK_DGRAM, 0 );
        if (s < 0) {
            perror("Cannot open socket");
            return 1;
        }
        ret = ioctl( s, SIOCGIFCONF, &ifc );
        if (s < 0) {
            perror("ioctl() failed");
            return 1;
        }
    
        for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq) ; i ++) {
            struct sockaddr_in *s;
            s = (struct sockaddr_in*)&ifc.ifc_req[i].ifr_addr;
            printf("%s\n", ifc.ifc_req[i].ifr_name);
            printf("%s\n", inet_ntoa(s->sin_addr));
        }
    }
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 526aaa2..ab15b86 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -112,7 +112,8 @@
   IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
   IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
   IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
-  IOCTL(SIOCGIFCONF, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifconf)))
+  IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
+                MK_PTR(MK_STRUCT(STRUCT_ifconf)))
   IOCTL(SIOCGIFENCAP, IOC_RW, MK_PTR(TYPE_INT))
   IOCTL(SIOCSIFENCAP, IOC_W, MK_PTR(TYPE_INT))
   IOCTL(SIOCDARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 732f71a..123909f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -59,6 +59,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 //#include <sys/user.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
+#include <net/if.h>
 #include <qemu-common.h>
 #ifdef TARGET_GPROF
 #include <sys/gmon.h>
@@ -2970,7 +2971,6 @@ static abi_long do_ipc(unsigned int call, int first,
 #endif
 
 /* kernel structure types definitions */
-#define IFNAMSIZ        16
 
 #define STRUCT(name, ...) STRUCT_ ## name,
 #define STRUCT_SPECIAL(name) STRUCT_ ## name,
@@ -3095,6 +3095,100 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
 }
 #endif
 
+static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                int fd, abi_long cmd, abi_long arg)
+{
+    const argtype *arg_type = ie->arg_type;
+    int target_size;
+    void *argptr;
+    int ret;
+    struct ifconf *host_ifconf;
+    uint32_t outbufsz;
+    const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
+    int target_ifreq_size;
+    int nb_ifreq;
+    int free_buf = 0;
+    int i;
+    int target_ifc_len;
+    abi_long target_ifc_buf;
+    int host_ifc_len;
+    char *host_ifc_buf;
+
+    assert(arg_type[0] == TYPE_PTR);
+    assert(ie->access == IOC_RW);
+
+    arg_type++;
+    target_size = thunk_type_size(arg_type, 0);
+
+    argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+    if (!argptr)
+        return -TARGET_EFAULT;
+    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+    unlock_user(argptr, arg, 0);
+
+    host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
+    target_ifc_len = host_ifconf->ifc_len;
+    target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
+
+    target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
+    nb_ifreq = target_ifc_len / target_ifreq_size;
+    host_ifc_len = nb_ifreq * sizeof(struct ifreq);
+
+    outbufsz = sizeof(*host_ifconf) + host_ifc_len;
+    if (outbufsz > MAX_STRUCT_SIZE) {
+        /* We can't fit all the extents into the fixed size buffer.
+         * Allocate one that is large enough and use it instead.
+         */
+        host_ifconf = malloc(outbufsz);
+        if (!host_ifconf) {
+            return -TARGET_ENOMEM;
+        }
+        memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
+        free_buf = 1;
+    }
+    host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
+
+    host_ifconf->ifc_len = host_ifc_len;
+    host_ifconf->ifc_buf = host_ifc_buf;
+
+    ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
+    if (!is_error(ret)) {
+	/* convert host ifc_len to target ifc_len */
+
+        nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
+        target_ifc_len = nb_ifreq * target_ifreq_size;
+        host_ifconf->ifc_len = target_ifc_len;
+
+	/* restore target ifc_buf */
+
+        host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
+
+	/* copy struct ifconf to target user */
+
+        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+        if (!argptr)
+            return -TARGET_EFAULT;
+        thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
+        unlock_user(argptr, arg, target_size);
+
+	/* copy ifreq[] to target user */
+
+        argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
+        for (i = 0; i < nb_ifreq ; i++) {
+            thunk_convert(argptr + i * target_ifreq_size,
+                          host_ifc_buf + i * sizeof(struct ifreq),
+                          ifreq_arg_type, THUNK_TARGET);
+        }
+        unlock_user(argptr, target_ifc_buf, target_ifc_len);
+    }
+
+    if (free_buf) {
+        free(host_ifconf);
+    }
+
+    return ret;
+}
+
 static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
commit 608e55921770bbae1609135aa0c351238f57fc5f
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Thu Apr 7 00:25:32 2011 +0200

    linux-user: improve traces
    
    Add trace details for getpid(), kill(), _llseek(), rt_sigaction(),
    rt_sigprocmask(), clone().
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 8dd398b..5d9bb08 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -9,6 +9,7 @@
 #include <sys/mount.h>
 #include <sys/mman.h>
 #include <unistd.h>
+#include <sched.h>
 #include "qemu.h"
 
 int do_strace=0;
@@ -63,6 +64,7 @@ UNUSED static void print_string(abi_long, int);
 UNUSED static void print_raw_param(const char *, abi_long, int);
 UNUSED static void print_timeval(abi_ulong, int);
 UNUSED static void print_number(abi_long, int);
+UNUSED static void print_signal(abi_ulong, int);
 
 /*
  * Utility functions
@@ -117,6 +119,37 @@ if( cmd == val ) { \
     gemu_log("%d",cmd);
 }
 
+static void
+print_signal(abi_ulong arg, int last)
+{
+    const char *signal_name = NULL;
+    switch(arg) {
+    case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
+    case TARGET_SIGINT: signal_name = "SIGINT"; break;
+    case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
+    case TARGET_SIGILL: signal_name = "SIGILL"; break;
+    case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
+    case TARGET_SIGFPE: signal_name = "SIGFPE"; break;
+    case TARGET_SIGKILL: signal_name = "SIGKILL"; break;
+    case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break;
+    case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break;
+    case TARGET_SIGALRM: signal_name = "SIGALRM"; break;
+    case TARGET_SIGTERM: signal_name = "SIGTERM"; break;
+    case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break;
+    case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break;
+    case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break;
+    case TARGET_SIGCONT: signal_name = "SIGCONT"; break;
+    case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break;
+    case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break;
+    case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
+    }
+    if (signal_name == NULL) {
+        print_raw_param("%ld", arg, 1);
+        return;
+    }
+    gemu_log("%s%s", signal_name, get_comma(last));
+}
+
 #ifdef TARGET_NR__newselect
 static void
 print_fdset(int n, abi_ulong target_fds_addr)
@@ -427,6 +460,32 @@ UNUSED static struct flags fcntl_flags[] = {
     FLAG_END,
 };
 
+UNUSED static struct flags clone_flags[] = {
+    FLAG_GENERIC(CLONE_VM),
+    FLAG_GENERIC(CLONE_FS),
+    FLAG_GENERIC(CLONE_FILES),
+    FLAG_GENERIC(CLONE_SIGHAND),
+    FLAG_GENERIC(CLONE_PTRACE),
+    FLAG_GENERIC(CLONE_VFORK),
+    FLAG_GENERIC(CLONE_PARENT),
+    FLAG_GENERIC(CLONE_THREAD),
+    FLAG_GENERIC(CLONE_NEWNS),
+    FLAG_GENERIC(CLONE_SYSVSEM),
+    FLAG_GENERIC(CLONE_SETTLS),
+    FLAG_GENERIC(CLONE_PARENT_SETTID),
+    FLAG_GENERIC(CLONE_CHILD_CLEARTID),
+    FLAG_GENERIC(CLONE_DETACHED),
+    FLAG_GENERIC(CLONE_UNTRACED),
+    FLAG_GENERIC(CLONE_CHILD_SETTID),
+    FLAG_GENERIC(CLONE_NEWUTS),
+    FLAG_GENERIC(CLONE_NEWIPC),
+    FLAG_GENERIC(CLONE_NEWUSER),
+    FLAG_GENERIC(CLONE_NEWPID),
+    FLAG_GENERIC(CLONE_NEWNET),
+    FLAG_GENERIC(CLONE_IO),
+    FLAG_END,
+};
+
 /*
  * print_xxx utility functions.  These are used to print syscall
  * parameters in certain format.  All of these have parameter
@@ -669,6 +728,39 @@ print_chmod(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_clone
+static void
+print_clone(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+#if defined(TARGET_M68K)
+    print_flags(clone_flags, arg0, 0);
+    print_raw_param("newsp=0x" TARGET_ABI_FMT_lx, arg1, 1);
+#elif defined(TARGET_SH4) || defined(TARGET_ALPHA)
+    print_flags(clone_flags, arg0, 0);
+    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0);
+    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg3, 0);
+    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#elif defined(TARGET_CRIS)
+    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg0, 0);
+    print_flags(clone_flags, arg1, 0);
+    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0);
+    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#else
+    print_flags(clone_flags, arg0, 0);
+    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0);
+    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0);
+    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0);
+    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1);
+#endif
+    print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_creat
 static void
 print_creat(const struct syscallname *name,
@@ -805,6 +897,28 @@ print_linkat(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR__llseek
+static void
+print__llseek(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    const char *whence = "UNKNOWN";
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_raw_param("%ld", arg1, 0);
+    print_raw_param("%ld", arg2, 0);
+    print_pointer(arg3, 0);
+    switch(arg4) {
+    case SEEK_SET: whence = "SEEK_SET"; break;
+    case SEEK_CUR: whence = "SEEK_CUR"; break;
+    case SEEK_END: whence = "SEEK_END"; break;
+    }
+    gemu_log("%s",whence);
+    print_syscall_epilogue(name);
+}
+#endif
+
 #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \
     defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64)
 static void
@@ -875,6 +989,40 @@ print_rmdir(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_rt_sigaction
+static void
+print_rt_sigaction(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_signal(arg0, 0);
+    print_pointer(arg1, 0);
+    print_pointer(arg2, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
+#ifdef TARGET_NR_rt_sigprocmask
+static void
+print_rt_sigprocmask(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    const char *how = "UNKNOWN";
+    print_syscall_prologue(name);
+    switch(arg0) {
+    case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break;
+    case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break;
+    case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break;
+    }
+    gemu_log("%s,",how);
+    print_pointer(arg1, 0);
+    print_pointer(arg2, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_mknod
 static void
 print_mknod(const struct syscallname *name,
@@ -1298,6 +1446,19 @@ print_futex(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_kill
+static void
+print_kill(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_signal(arg1, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
 /*
  * An array of all of the syscalls we know about
  */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 563a67f..a7eeaef 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -85,7 +85,7 @@
 { TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_clone
-{ TARGET_NR_clone, "clone" , NULL, NULL, NULL },
+{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL },
 #endif
 #ifdef TARGET_NR_close
 { TARGET_NR_close, "close" , "%s(%d)", NULL, NULL },
@@ -292,7 +292,7 @@
 { TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_getpid
-{ TARGET_NR_getpid, "getpid" , NULL, NULL, NULL },
+{ TARGET_NR_getpid, "getpid" , "%s()", NULL, NULL },
 #endif
 #ifdef TARGET_NR_getpmsg
 { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
@@ -418,7 +418,7 @@
 { TARGET_NR_keyctl, "keyctl" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_kill
-{ TARGET_NR_kill, "kill" , NULL, NULL, NULL },
+{ TARGET_NR_kill, "kill", NULL, print_kill, NULL },
 #endif
 #ifdef TARGET_NR_lchown
 { TARGET_NR_lchown, "lchown" , NULL, NULL, NULL },
@@ -448,7 +448,7 @@
 { TARGET_NR_llistxattr, "llistxattr" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR__llseek
-{ TARGET_NR__llseek, "_llseek" , NULL, NULL, NULL },
+{ TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL },
 #endif
 #ifdef TARGET_NR_lock
 { TARGET_NR_lock, "lock" , NULL, NULL, NULL },
@@ -1063,13 +1063,13 @@
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigaction
-{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, print_rt_sigaction, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigpending
 { TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigprocmask
-{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigqueueinfo
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, NULL, NULL },
commit 05098a9315819621405eb662baddeec624127d7a
Author: Riku Voipio <riku.voipio at nokia.com>
Date:   Fri Mar 4 15:27:29 2011 +0200

    [v2] linux-user: bigger default stack
    
    PTHREAD_STACK_MIN (16KB) is somewhat inadequate for a new stack for new
    QEMU threads. Set new limit to 256K which should be enough, yet doesn't
    increase memory pressure significantly.
    
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
    Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb0999d..732f71a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3690,9 +3690,9 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 
 #endif /* defined(TARGET_I386) */
 
-#if defined(CONFIG_USE_NPTL)
+#define NEW_STACK_SIZE 0x40000
 
-#define NEW_STACK_SIZE PTHREAD_STACK_MIN
+#if defined(CONFIG_USE_NPTL)
 
 static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
 typedef struct {
@@ -3736,9 +3736,6 @@ static void *clone_func(void *arg)
     return NULL;
 }
 #else
-/* this stack is the equivalent of the kernel stack associated with a
-   thread/process */
-#define NEW_STACK_SIZE 8192
 
 static int clone_func(void *arg)
 {
commit b0b36e5d2e4c8a96c2f6dbc0981a9fd0cde111d8
Author: Brad Hards <bradh at frogmouth.net>
Date:   Sun Apr 24 17:19:56 2011 +1000

    doc: fix slirp description
    
    net/slirp.c says:
        /* default settings according to historic slirp */
        struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
        struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
        struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
        struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
        struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
    
    Which I think is not what the documentation says.
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/qemu-options.hx b/qemu-options.hx
index 677c550..489df10 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1152,7 +1152,7 @@ Assign symbolic name for use in monitor commands.
 @item net=@var{addr}[/@var{mask}]
 Set IP network address the guest will see. Optionally specify the netmask,
 either in the form a.b.c.d or as number of valid top-most bits. Default is
-10.0.2.0/8.
+10.0.2.0/24.
 
 @item host=@var{addr}
 Specify the guest-visible address of the host. Default is the 2nd IP in the
@@ -1168,7 +1168,7 @@ Specifies the client hostname reported by the builtin DHCP server.
 
 @item dhcpstart=@var{addr}
 Specify the first of the 16 IPs the built-in DHCP server can assign. Default
-is the 16th to 31st IP in the guest network, i.e. x.x.x.16 to x.x.x.31.
+is the 15th to 31st IP in the guest network, i.e. x.x.x.15 to x.x.x.31.
 
 @item dns=@var{addr}
 Specify the guest-visible address of the virtual nameserver. The address must
commit ec48c7747acd1be25ca70586bc4e6640765e40c8
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Wed Apr 20 19:39:02 2011 -0400

    rtl8139: add format attribute to DPRINTF
    
    gcc can check the format string for correctness even when debugging output is
    not enabled.
    Have to make sure arguments are always available. They are optimized out if
    unneeded.
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Cc: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 13b14e4..cbf667a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -88,7 +88,11 @@
 #  define DPRINTF(fmt, ...) \
     do { fprintf(stderr, "RTL8139: " fmt, ## __VA_ARGS__); } while (0)
 #else
-#  define DPRINTF(fmt, ...) do { } while (0)
+static inline __attribute__ ((format (printf, 1, 2)))
+    int DPRINTF(const char *fmt, ...)
+{
+    return 0;
+}
 #endif
 
 /* Symbolic offsets to registers. */
@@ -2201,9 +2205,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
                 if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
                 {
-#if defined (DEBUG_RTL8139)
                     int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
-#endif
+
                     DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
                         "frame data %d specified MSS=%d\n", ETH_MTU,
                         ip_data_len, saved_size - ETH_HLEN, large_send_mss);
commit 7cdeb319e46b8aeef866e17119093e1646e77b02
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Wed Apr 20 19:39:01 2011 -0400

    rtl8139: use variadic macro for debug statements
    
    Removes double (( )) to make DEBUG_PRINT compatible with real function calls.
    Change the name to DPRINTF to be consistent with other DPRINTF macros
    throughout qemu.
    Include the "RTL8139: " prefix in the macro. This changes some debug output
    slightly since the prefix wasn't present on all lines.
    
    Part of the change was done using the "coccinelle" tool with the following
    small semantic match:
        @@ expression E; @@
    
        - DEBUG_PRINT((E))
        + DPRINTF(E)
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Cc: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index a46416e..13b14e4 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -85,9 +85,10 @@
 #define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN)
 
 #if defined (DEBUG_RTL8139)
-#  define DEBUG_PRINT(x) do { printf x ; } while (0)
+#  define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, "RTL8139: " fmt, ## __VA_ARGS__); } while (0)
 #else
-#  define DEBUG_PRINT(x)
+#  define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
 /* Symbolic offsets to registers. */
@@ -510,7 +511,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time);
 
 static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
 {
-    DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
+    DPRINTF("eeprom command 0x%02x\n", command);
 
     switch (command & Chip9346_op_mask)
     {
@@ -521,8 +522,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
             eeprom->eedo = 0;
             eeprom->tick = 0;
             eeprom->mode = Chip9346_data_read;
-            DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
-                   eeprom->address, eeprom->output));
+            DPRINTF("eeprom read from address 0x%02x data=0x%04x\n",
+                eeprom->address, eeprom->output);
         }
         break;
 
@@ -532,8 +533,8 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
             eeprom->input = 0;
             eeprom->tick = 0;
             eeprom->mode = Chip9346_none; /* Chip9346_data_write */
-            DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",
-                   eeprom->address));
+            DPRINTF("eeprom begin write to address 0x%02x\n",
+                eeprom->address);
         }
         break;
         default:
@@ -541,13 +542,13 @@ static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
             switch (command & Chip9346_op_ext_mask)
             {
                 case Chip9346_op_write_enable:
-                    DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));
+                    DPRINTF("eeprom write enabled\n");
                     break;
                 case Chip9346_op_write_all:
-                    DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));
+                    DPRINTF("eeprom begin write all\n");
                     break;
                 case Chip9346_op_write_disable:
-                    DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));
+                    DPRINTF("eeprom write disabled\n");
                     break;
             }
             break;
@@ -560,7 +561,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
 
     ++ eeprom->tick;
 
-    DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo));
+    DPRINTF("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi,
+        eeprom->eedo);
 
     switch (eeprom->mode)
     {
@@ -570,7 +572,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
                 eeprom->mode = Chip9346_read_command;
                 eeprom->tick = 0;
                 eeprom->input = 0;
-                DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n"));
+                DPRINTF("eeprom: +++ synchronized, begin command read\n");
             }
             break;
 
@@ -595,7 +597,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
                 eeprom->input = 0;
                 eeprom->tick = 0;
 
-                DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n"));
+                DPRINTF("eeprom: +++ end of read, awaiting next command\n");
 #else
         // original behaviour
                 ++eeprom->address;
@@ -603,8 +605,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
                 eeprom->output = eeprom->contents[eeprom->address];
                 eeprom->tick = 0;
 
-                DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
-                       eeprom->address, eeprom->output));
+                DPRINTF("eeprom: +++ read next address 0x%02x data=0x%04x\n",
+                    eeprom->address, eeprom->output);
 #endif
             }
             break;
@@ -613,8 +615,8 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
             eeprom->input = (eeprom->input << 1) | (bit & 1);
             if (eeprom->tick == 16)
             {
-                DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
-                       eeprom->address, eeprom->input));
+                DPRINTF("eeprom write to address 0x%02x data=0x%04x\n",
+                    eeprom->address, eeprom->input);
 
                 eeprom->contents[eeprom->address] = eeprom->input;
                 eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
@@ -632,8 +634,7 @@ static void prom9346_shift_clock(EEprom9346 *eeprom)
                 {
                     eeprom->contents[i] = eeprom->input;
                 }
-                DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",
-                       eeprom->input));
+                DPRINTF("eeprom filled with data=0x%04x\n", eeprom->input);
 
                 eeprom->mode = Chip9346_enter_command_mode;
                 eeprom->tick = 0;
@@ -666,8 +667,8 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
     eeprom->eesk = eesk;
     eeprom->eedi = eedi;
 
-    DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
-                 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));
+    DPRINTF("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs,
+        eeprom->eesk, eeprom->eedi, eeprom->eedo);
 
     if (!old_eecs && eecs)
     {
@@ -677,12 +678,12 @@ static void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
         eeprom->output = 0;
         eeprom->mode = Chip9346_enter_command_mode;
 
-        DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));
+        DPRINTF("=== eeprom: begin access, enter command mode\n");
     }
 
     if (!eecs)
     {
-        DEBUG_PRINT(("=== eeprom: end access\n"));
+        DPRINTF("=== eeprom: end access\n");
         return;
     }
 
@@ -698,8 +699,8 @@ static void rtl8139_update_irq(RTL8139State *s)
     int isr;
     isr = (s->IntrStatus & s->IntrMask) & 0xffff;
 
-    DEBUG_PRINT(("RTL8139: Set IRQ to %d (%04x %04x)\n",
-       isr ? 1 : 0, s->IntrStatus, s->IntrMask));
+    DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
+        s->IntrMask);
 
     qemu_set_irq(s->dev.irq[0], (isr != 0));
 }
@@ -763,7 +764,7 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
         /* write packet data */
         if (wrapped && !(s->RxBufferSize < 65536 && rtl8139_RxWrap(s)))
         {
-            DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped));
+            DPRINTF(">>> rx packet wrapped in buffer at %d\n", size - wrapped);
 
             if (size > wrapped)
             {
@@ -834,12 +835,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
     static const uint8_t broadcast_macaddr[6] =
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
-    DEBUG_PRINT((">>> RTL8139: received len=%d\n", size));
+    DPRINTF(">>> received len=%d\n", size);
 
     /* test if board clock is stopped */
     if (!s->clock_enabled)
     {
-        DEBUG_PRINT(("RTL8139: stopped ==========================\n"));
+        DPRINTF("stopped ==========================\n");
         return -1;
     }
 
@@ -847,21 +848,21 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
     if (!rtl8139_receiver_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: receiver disabled ================\n"));
+        DPRINTF("receiver disabled ================\n");
         return -1;
     }
 
     /* XXX: check this */
     if (s->RxConfig & AcceptAllPhys) {
         /* promiscuous: receive all */
-        DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n"));
+        DPRINTF(">>> packet received in promiscuous mode\n");
 
     } else {
         if (!memcmp(buf,  broadcast_macaddr, 6)) {
             /* broadcast address */
             if (!(s->RxConfig & AcceptBroadcast))
             {
-                DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n"));
+                DPRINTF(">>> broadcast packet rejected\n");
 
                 /* update tally counter */
                 ++s->tally_counters.RxERR;
@@ -871,7 +872,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
             packet_header |= RxBroadcast;
 
-            DEBUG_PRINT((">>> RTL8139: broadcast packet received\n"));
+            DPRINTF(">>> broadcast packet received\n");
 
             /* update tally counter */
             ++s->tally_counters.RxOkBrd;
@@ -880,7 +881,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
             /* multicast */
             if (!(s->RxConfig & AcceptMulticast))
             {
-                DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n"));
+                DPRINTF(">>> multicast packet rejected\n");
 
                 /* update tally counter */
                 ++s->tally_counters.RxERR;
@@ -892,7 +893,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
             if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
             {
-                DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n"));
+                DPRINTF(">>> multicast address mismatch\n");
 
                 /* update tally counter */
                 ++s->tally_counters.RxERR;
@@ -902,7 +903,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
             packet_header |= RxMulticast;
 
-            DEBUG_PRINT((">>> RTL8139: multicast packet received\n"));
+            DPRINTF(">>> multicast packet received\n");
 
             /* update tally counter */
             ++s->tally_counters.RxOkMul;
@@ -916,7 +917,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
             /* match */
             if (!(s->RxConfig & AcceptMyPhys))
             {
-                DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n"));
+                DPRINTF(">>> rejecting physical address matching packet\n");
 
                 /* update tally counter */
                 ++s->tally_counters.RxERR;
@@ -926,14 +927,14 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
             packet_header |= RxPhysical;
 
-            DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n"));
+            DPRINTF(">>> physical address matching packet received\n");
 
             /* update tally counter */
             ++s->tally_counters.RxOkPhy;
 
         } else {
 
-            DEBUG_PRINT((">>> RTL8139: unknown packet\n"));
+            DPRINTF(">>> unknown packet\n");
 
             /* update tally counter */
             ++s->tally_counters.RxERR;
@@ -955,7 +956,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
     if (rtl8139_cp_receiver_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n"));
+        DPRINTF("in C+ Rx mode ================\n");
 
         /* begin C+ receiver mode */
 
@@ -978,9 +979,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
         cplus_rx_ring_desc += 16 * descriptor;
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from "
-                "host memory at %08x %08x = " TARGET_FMT_plx "\n", descriptor,
-                s->RxRingAddrHI, s->RxRingAddrLO, cplus_rx_ring_desc));
+        DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at "
+            "%08x %08x = "TARGET_FMT_plx"\n", descriptor, s->RxRingAddrHI,
+            s->RxRingAddrLO, cplus_rx_ring_desc);
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
@@ -993,13 +994,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
         rxbufHI = le32_to_cpu(val);
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
-               descriptor,
-               rxdw0, rxdw1, rxbufLO, rxbufHI));
+        DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
+            descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI);
 
         if (!(rxdw0 & CP_RX_OWN))
         {
-            DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor));
+            DPRINTF("C+ Rx mode : descriptor %d is owned by host\n",
+                descriptor);
 
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
@@ -1029,9 +1030,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
             rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)
                 &dot1q_buf[ETHER_TYPE_LEN]);
 
-            DEBUG_PRINT(("RTL8139: C+ Rx mode : extracted vlan tag with tci: "
-                    "%u\n", be16_to_cpup((uint16_t *)
-                        &dot1q_buf[ETHER_TYPE_LEN])));
+            DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n",
+                be16_to_cpup((uint16_t *)&dot1q_buf[ETHER_TYPE_LEN]));
         } else {
             /* reset VLAN tag flag */
             rxdw1 &= ~CP_RX_TAVA;
@@ -1041,8 +1041,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         if (size+4 > rx_space)
         {
-            DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n",
-                   descriptor, rx_space, size));
+            DPRINTF("C+ Rx mode : descriptor %d size %d received %d + 4\n",
+                descriptor, rx_space, size);
 
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
@@ -1137,12 +1137,12 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
             ++s->currCPlusRxDesc;
         }
 
-        DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n"));
+        DPRINTF("done C+ Rx mode ----------------\n");
 
     }
     else
     {
-        DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n"));
+        DPRINTF("in ring Rx mode ================\n");
 
         /* begin ring receiver mode */
         int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize);
@@ -1151,8 +1151,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         if (avail != 0 && size + 8 >= avail)
         {
-            DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
-                   s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8));
+            DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
+                "read 0x%04x === available 0x%04x need 0x%04x\n",
+                s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8);
 
             s->IntrStatus |= RxOverflow;
             ++s->RxMissed;
@@ -1180,8 +1181,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         /* now we can signal we have received something */
 
-        DEBUG_PRINT(("   received: rx buffer length %d head 0x%04x read 0x%04x\n",
-               s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
+        DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n",
+            s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
     }
 
     s->IntrStatus |= RxOK;
@@ -1375,22 +1376,22 @@ static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val));
+    DPRINTF("ChipCmd write val=0x%08x\n", val);
 
     if (val & CmdReset)
     {
-        DEBUG_PRINT(("RTL8139: ChipCmd reset\n"));
+        DPRINTF("ChipCmd reset\n");
         rtl8139_reset(&s->dev.qdev);
     }
     if (val & CmdRxEnb)
     {
-        DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n"));
+        DPRINTF("ChipCmd enable receiver\n");
 
         s->currCPlusRxDesc = 0;
     }
     if (val & CmdTxEnb)
     {
-        DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n"));
+        DPRINTF("ChipCmd enable transmitter\n");
 
         s->currCPlusTxDesc = 0;
     }
@@ -1410,11 +1411,11 @@ static int rtl8139_RxBufferEmpty(RTL8139State *s)
 
     if (unread != 0)
     {
-        DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", unread));
+        DPRINTF("receiver buffer data available 0x%04x\n", unread);
         return 0;
     }
 
-    DEBUG_PRINT(("RTL8139: receiver buffer is empty\n"));
+    DPRINTF("receiver buffer is empty\n");
 
     return 1;
 }
@@ -1426,7 +1427,7 @@ static uint32_t rtl8139_ChipCmd_read(RTL8139State *s)
     if (rtl8139_RxBufferEmpty(s))
         ret |= RxBufEmpty;
 
-    DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret));
+    DPRINTF("ChipCmd read val=0x%04x\n", ret);
 
     return ret;
 }
@@ -1435,7 +1436,7 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xffff;
 
-    DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val));
+    DPRINTF("C+ command register write(w) val=0x%04x\n", val);
 
     s->cplus_enabled = 1;
 
@@ -1449,21 +1450,21 @@ static uint32_t rtl8139_CpCmd_read(RTL8139State *s)
 {
     uint32_t ret = s->CpCmd;
 
-    DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret));
+    DPRINTF("C+ command register read(w) val=0x%04x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", val));
+    DPRINTF("C+ IntrMitigate register write(w) val=0x%04x\n", val);
 }
 
 static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
 {
     uint32_t ret = 0;
 
-    DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret));
+    DPRINTF("C+ IntrMitigate register read(w) val=0x%04x\n", ret);
 
     return ret;
 }
@@ -1475,7 +1476,7 @@ static int rtl8139_config_writeable(RTL8139State *s)
         return 1;
     }
 
-    DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n"));
+    DPRINTF("Configuration registers are write-protected\n");
 
     return 0;
 }
@@ -1484,7 +1485,7 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xffff;
 
-    DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val));
+    DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val);
 
     /* mask unwriteable bits */
     uint32_t mask = 0x4cff;
@@ -1506,7 +1507,7 @@ static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s)
 {
     uint32_t ret = s->BasicModeCtrl;
 
-    DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret));
+    DPRINTF("BasicModeCtrl register read(w) val=0x%04x\n", ret);
 
     return ret;
 }
@@ -1515,7 +1516,7 @@ static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xffff;
 
-    DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val));
+    DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xff3f, s->BasicModeStatus);
@@ -1527,7 +1528,7 @@ static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s)
 {
     uint32_t ret = s->BasicModeStatus;
 
-    DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret));
+    DPRINTF("BasicModeStatus register read(w) val=0x%04x\n", ret);
 
     return ret;
 }
@@ -1536,7 +1537,7 @@ static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val));
+    DPRINTF("Cfg9346 write val=0x%02x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x31, s->Cfg9346);
@@ -1579,7 +1580,7 @@ static uint32_t rtl8139_Cfg9346_read(RTL8139State *s)
         }
     }
 
-    DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret));
+    DPRINTF("Cfg9346 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1588,7 +1589,7 @@ static void rtl8139_Config0_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val));
+    DPRINTF("Config0 write val=0x%02x\n", val);
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1603,7 +1604,7 @@ static uint32_t rtl8139_Config0_read(RTL8139State *s)
 {
     uint32_t ret = s->Config0;
 
-    DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret));
+    DPRINTF("Config0 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1612,7 +1613,7 @@ static void rtl8139_Config1_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val));
+    DPRINTF("Config1 write val=0x%02x\n", val);
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1627,7 +1628,7 @@ static uint32_t rtl8139_Config1_read(RTL8139State *s)
 {
     uint32_t ret = s->Config1;
 
-    DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret));
+    DPRINTF("Config1 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1636,7 +1637,7 @@ static void rtl8139_Config3_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val));
+    DPRINTF("Config3 write val=0x%02x\n", val);
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1651,7 +1652,7 @@ static uint32_t rtl8139_Config3_read(RTL8139State *s)
 {
     uint32_t ret = s->Config3;
 
-    DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret));
+    DPRINTF("Config3 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1660,7 +1661,7 @@ static void rtl8139_Config4_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val));
+    DPRINTF("Config4 write val=0x%02x\n", val);
 
     if (!rtl8139_config_writeable(s))
         return;
@@ -1675,7 +1676,7 @@ static uint32_t rtl8139_Config4_read(RTL8139State *s)
 {
     uint32_t ret = s->Config4;
 
-    DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret));
+    DPRINTF("Config4 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1684,7 +1685,7 @@ static void rtl8139_Config5_write(RTL8139State *s, uint32_t val)
 {
     val &= 0xff;
 
-    DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val));
+    DPRINTF("Config5 write val=0x%02x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x80, s->Config5);
@@ -1696,7 +1697,7 @@ static uint32_t rtl8139_Config5_read(RTL8139State *s)
 {
     uint32_t ret = s->Config5;
 
-    DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret));
+    DPRINTF("Config5 read val=0x%02x\n", ret);
 
     return ret;
 }
@@ -1705,11 +1706,11 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val)
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val));
+        DPRINTF("transmitter disabled; no TxConfig write val=0x%08x\n", val);
         return;
     }
 
-    DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val));
+    DPRINTF("TxConfig write val=0x%08x\n", val);
 
     val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig);
 
@@ -1718,7 +1719,7 @@ static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val)
 
 static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val));
+    DPRINTF("RTL8139C TxConfig via write(b) val=0x%02x\n", val);
 
     uint32_t tc = s->TxConfig;
     tc &= 0xFFFFFF00;
@@ -1730,14 +1731,14 @@ static uint32_t rtl8139_TxConfig_read(RTL8139State *s)
 {
     uint32_t ret = s->TxConfig;
 
-    DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret));
+    DPRINTF("TxConfig read val=0x%04x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val));
+    DPRINTF("RxConfig write val=0x%08x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xf0fc0040, s->RxConfig);
@@ -1747,14 +1748,14 @@ static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
     /* reset buffer size and read/write pointers */
     rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3));
 
-    DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize));
+    DPRINTF("RxConfig write reset buffer size to %d\n", s->RxBufferSize);
 }
 
 static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
 {
     uint32_t ret = s->RxConfig;
 
-    DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret));
+    DPRINTF("RxConfig read val=0x%08x\n", ret);
 
     return ret;
 }
@@ -1766,7 +1767,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
 
     if (!size)
     {
-        DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
+        DPRINTF("+++ empty ethernet frame\n");
         return;
     }
 
@@ -1791,7 +1792,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
             buf = buf2;
         }
 
-        DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
+        DPRINTF("+++ transmit loopback mode\n");
         rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt);
 
         if (iov) {
@@ -1812,25 +1813,25 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n",
-                     descriptor));
+        DPRINTF("+++ cannot transmit from descriptor %d: transmitter "
+            "disabled\n", descriptor);
         return 0;
     }
 
     if (s->TxStatus[descriptor] & TxHostOwns)
     {
-        DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n",
-                     descriptor, s->TxStatus[descriptor]));
+        DPRINTF("+++ cannot transmit from descriptor %d: owned by host "
+            "(%08x)\n", descriptor, s->TxStatus[descriptor]);
         return 0;
     }
 
-    DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", descriptor));
+    DPRINTF("+++ transmitting from descriptor %d\n", descriptor);
 
     int txsize = s->TxStatus[descriptor] & 0x1fff;
     uint8_t txbuffer[0x2000];
 
-    DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n",
-                 txsize, s->TxAddr[descriptor]));
+    DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n",
+        txsize, s->TxAddr[descriptor]);
 
     cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize);
 
@@ -1840,7 +1841,8 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
 
     rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL);
 
-    DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
+    DPRINTF("+++ transmitted %d bytes from descriptor %d\n", txsize,
+        descriptor);
 
     /* update interrupt */
     s->IntrStatus |= TxOK;
@@ -1940,13 +1942,13 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 {
     if (!rtl8139_transmitter_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n"));
+        DPRINTF("+++ C+ mode: transmitter disabled\n");
         return 0;
     }
 
     if (!rtl8139_cp_transmitter_enabled(s))
     {
-        DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n"));
+        DPRINTF("+++ C+ mode: C+ transmitter disabled\n");
         return 0 ;
     }
 
@@ -1958,9 +1960,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     /* Normal priority ring */
     cplus_tx_ring_desc += 16 * descriptor;
 
-    DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host "
-            "memory at %08x0x%08x = 0x" TARGET_FMT_plx "\n", descriptor,
-            s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
+    DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
+        "%08x0x%08x = 0x"TARGET_FMT_plx"\n", descriptor, s->TxAddr[1],
+        s->TxAddr[0], cplus_tx_ring_desc);
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
 
@@ -1973,9 +1975,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
     txbufHI = le32_to_cpu(val);
 
-    DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n",
-           descriptor,
-           txdw0, txdw1, txbufLO, txbufHI));
+    DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor,
+        txdw0, txdw1, txbufLO, txbufHI);
 
 /* w0 ownership flag */
 #define CP_TX_OWN (1<<31)
@@ -2021,15 +2022,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     if (!(txdw0 & CP_TX_OWN))
     {
-        DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor));
+        DPRINTF("C+ Tx mode : descriptor %d is owned by host\n", descriptor);
         return 0 ;
     }
 
-    DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor));
+    DPRINTF("+++ C+ Tx mode : transmitting from descriptor %d\n", descriptor);
 
     if (txdw0 & CP_TX_FS)
     {
-        DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor));
+        DPRINTF("+++ C+ Tx mode : descriptor %d is first segment "
+            "descriptor\n", descriptor);
 
         /* reset internal buffer offset */
         s->cplus_txbuffer_offset = 0;
@@ -2045,7 +2047,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         s->cplus_txbuffer = qemu_malloc(s->cplus_txbuffer_len);
         s->cplus_txbuffer_offset = 0;
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len));
+        DPRINTF("+++ C+ mode transmission buffer allocated space %d\n",
+            s->cplus_txbuffer_len);
     }
 
     while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
@@ -2053,14 +2056,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
         s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len));
+        DPRINTF("+++ C+ mode transmission buffer space changed to %d\n",
+            s->cplus_txbuffer_len);
     }
 
     if (!s->cplus_txbuffer)
     {
         /* out of memory */
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d bytes\n", s->cplus_txbuffer_len));
+        DPRINTF("+++ C+ mode transmiter failed to reallocate %d bytes\n",
+            s->cplus_txbuffer_len);
 
         /* update tally counter */
         ++s->tally_counters.TxERR;
@@ -2071,9 +2076,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     /* append more data to the packet */
 
-    DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host "
-            "memory at " TARGET_FMT_plx " to offset %d\n", txsize, tx_addr,
-            s->cplus_txbuffer_offset));
+    DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at "
+        TARGET_FMT_plx" to offset %d\n", txsize, tx_addr,
+        s->cplus_txbuffer_offset);
 
     cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
     s->cplus_txbuffer_offset += txsize;
@@ -2110,7 +2115,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         uint8_t dot1q_buffer_space[VLAN_HLEN];
         uint16_t *dot1q_buffer;
 
-        DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
+        DPRINTF("+++ C+ Tx mode : descriptor %d is last segment descriptor\n",
+            descriptor);
 
         /* can transfer fully assembled packet */
 
@@ -2122,8 +2128,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         if (txdw1 & CP_TX_TAGC) {
             /* the vlan tag is in BE byte order in the descriptor
              * BE + le_to_cpu() + ~swap()~ = cpu */
-            DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with "
-                    "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)));
+            DPRINTF("+++ C+ Tx mode : inserting vlan tag with ""tci: %u\n",
+                bswap16(txdw1 & CP_TX_VLAN_TAG_MASK));
 
             dot1q_buffer = (uint16_t *) dot1q_buffer_space;
             dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
@@ -2140,7 +2146,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
         if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN))
         {
-            DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n"));
+            DPRINTF("+++ C+ mode offloaded task checksum\n");
 
             /* ip packet header */
             ip_header *ip = NULL;
@@ -2154,7 +2160,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
             int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
             if (proto == ETH_P_IP)
             {
-                DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
+                DPRINTF("+++ C+ mode has IP packet\n");
 
                 /* not aligned */
                 eth_payload_data = saved_buffer + ETH_HLEN;
@@ -2163,7 +2169,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                 ip = (ip_header*)eth_payload_data;
 
                 if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
-                    DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4));
+                    DPRINTF("+++ C+ mode packet has bad IP version %d "
+                        "expected %d\n", IP_HEADER_VERSION(ip),
+                        IP_HEADER_VERSION_4);
                     ip = NULL;
                 } else {
                     hlen = IP_HEADER_LENGTH(ip);
@@ -2176,7 +2184,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
             {
                 if (txdw0 & CP_TX_IPCS)
                 {
-                    DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
+                    DPRINTF("+++ C+ mode need IP checksum\n");
 
                     if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
                         /* bad packet header len */
@@ -2186,7 +2194,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                     {
                         ip->ip_sum = 0;
                         ip->ip_sum = ip_checksum(ip, hlen);
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
+                        DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
+                            hlen, ip->ip_sum);
                     }
                 }
 
@@ -2195,8 +2204,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 #if defined (DEBUG_RTL8139)
                     int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
 #endif
-                    DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
-                                 ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss));
+                    DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
+                        "frame data %d specified MSS=%d\n", ETH_MTU,
+                        ip_data_len, saved_size - ETH_HLEN, large_send_mss);
 
                     int tcp_send_offset = 0;
                     int send_count = 0;
@@ -2220,8 +2230,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                     int tcp_data_len = ip_data_len - tcp_hlen;
                     int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
 
-                    DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n",
-                                 ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size));
+                    DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
+                        "data len %d TCP chunk size %d\n", ip_data_len,
+                        tcp_hlen, tcp_data_len, tcp_chunk_size);
 
                     /* note the cycle below overwrites IP header data,
                        but restores it from saved_ip_header before sending packet */
@@ -2239,13 +2250,16 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                             chunk_size = tcp_data_len - tcp_send_offset;
                         }
 
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
+                        DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
+                            be32_to_cpu(p_tcp_hdr->th_seq));
 
                         /* add 4 TCP pseudoheader fields */
                         /* copy IP source and destination fields */
                         memcpy(data_to_checksum, saved_ip_header + 12, 8);
 
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
+                        DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
+                            "packet with %d bytes data\n", tcp_hlen +
+                            chunk_size);
 
                         if (tcp_send_offset)
                         {
@@ -2267,7 +2281,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                         p_tcp_hdr->th_sum = 0;
 
                         int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum));
+                        DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
+                            tcp_checksum);
 
                         p_tcp_hdr->th_sum = tcp_checksum;
 
@@ -2282,10 +2297,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
                         ip->ip_sum = 0;
                         ip->ip_sum = ip_checksum(eth_payload_data, hlen);
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
+                        DPRINTF("+++ C+ mode TSO IP header len=%d "
+                            "checksum=%04x\n", hlen, ip->ip_sum);
 
                         int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
+                        DPRINTF("+++ C+ mode TSO transferring packet size "
+                            "%d\n", tso_send_size);
                         rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
                             0, (uint8_t *) dot1q_buffer);
 
@@ -2299,7 +2316,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                 }
                 else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
                 {
-                    DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n"));
+                    DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
 
                     /* maximum IP header length is 60 bytes */
                     uint8_t saved_ip_header[60];
@@ -2314,7 +2331,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
                     if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
                     {
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
+                        DPRINTF("+++ C+ mode calculating TCP checksum for "
+                            "packet with %d bytes data\n", ip_data_len);
 
                         ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
                         p_tcpip_hdr->zeros      = 0;
@@ -2326,13 +2344,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                         p_tcp_hdr->th_sum = 0;
 
                         int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum));
+                        DPRINTF("+++ C+ mode TCP checksum %04x\n",
+                            tcp_checksum);
 
                         p_tcp_hdr->th_sum = tcp_checksum;
                     }
                     else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
                     {
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len));
+                        DPRINTF("+++ C+ mode calculating UDP checksum for "
+                            "packet with %d bytes data\n", ip_data_len);
 
                         ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
                         p_udpip_hdr->zeros      = 0;
@@ -2344,7 +2364,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
                         p_udp_hdr->uh_sum = 0;
 
                         int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
-                        DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum));
+                        DPRINTF("+++ C+ mode UDP checksum %04x\n",
+                            udp_checksum);
 
                         p_udp_hdr->uh_sum = udp_checksum;
                     }
@@ -2358,7 +2379,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         /* update tally counter */
         ++s->tally_counters.TxOk;
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
+        DPRINTF("+++ C+ mode transmitting %d bytes packet\n", saved_size);
 
         rtl8139_transfer_frame(s, saved_buffer, saved_size, 1,
             (uint8_t *) dot1q_buffer);
@@ -2377,7 +2398,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     }
     else
     {
-        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next descriptor\n"));
+        DPRINTF("+++ C+ mode transmission continue to next descriptor\n");
     }
 
     return 1;
@@ -2395,8 +2416,8 @@ static void rtl8139_cplus_transmit(RTL8139State *s)
     /* Mark transfer completed */
     if (!txcount)
     {
-        DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n",
-                     s->currCPlusTxDesc));
+        DPRINTF("C+ mode : transmitter queue stalled, current TxDesc = %d\n",
+            s->currCPlusTxDesc);
     }
     else
     {
@@ -2421,7 +2442,8 @@ static void rtl8139_transmit(RTL8139State *s)
     /* Mark transfer completed */
     if (!txcount)
     {
-        DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc));
+        DPRINTF("transmitter queue stalled, current TxDesc = %d\n",
+            s->currTxDesc);
     }
 }
 
@@ -2434,7 +2456,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
 
     if (s->cplus_enabled)
     {
-        DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
+        DPRINTF("RTL8139C+ DTCCR write offset=0x%x val=0x%08x "
+            "descriptor=%d\n", txRegOffset, val, descriptor);
 
         /* handle Dump Tally Counters command */
         s->TxStatus[descriptor] = val;
@@ -2453,7 +2476,8 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
         return;
     }
 
-    DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
+    DPRINTF("TxStatus write offset=0x%x val=0x%08x descriptor=%d\n",
+        txRegOffset, val, descriptor);
 
     /* mask only reserved bits */
     val &= ~0xff00c000; /* these bits are reset on write */
@@ -2469,7 +2493,7 @@ static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset)
 {
     uint32_t ret = s->TxStatus[txRegOffset/4];
 
-    DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret));
+    DPRINTF("TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret);
 
     return ret;
 }
@@ -2501,7 +2525,7 @@ static uint16_t rtl8139_TSAD_read(RTL8139State *s)
          |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ;
 
 
-    DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret));
+    DPRINTF("TSAD read val=0x%04x\n", ret);
 
     return ret;
 }
@@ -2510,14 +2534,14 @@ static uint16_t rtl8139_CSCR_read(RTL8139State *s)
 {
     uint16_t ret = s->CSCR;
 
-    DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret));
+    DPRINTF("CSCR read val=0x%04x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val));
+    DPRINTF("TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val);
 
     s->TxAddr[txAddrOffset/4] = val;
 }
@@ -2526,20 +2550,20 @@ static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset)
 {
     uint32_t ret = s->TxAddr[txAddrOffset/4];
 
-    DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret));
+    DPRINTF("TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret);
 
     return ret;
 }
 
 static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val));
+    DPRINTF("RxBufPtr write val=0x%04x\n", val);
 
     /* this value is off by 16 */
     s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
 
-    DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
-           s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
+    DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
+        s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
 }
 
 static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
@@ -2547,7 +2571,7 @@ static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
     /* this value is off by 16 */
     uint32_t ret = s->RxBufPtr - 0x10;
 
-    DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret));
+    DPRINTF("RxBufPtr read val=0x%04x\n", ret);
 
     return ret;
 }
@@ -2557,14 +2581,14 @@ static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s)
     /* this value is NOT off by 16 */
     uint32_t ret = s->RxBufAddr;
 
-    DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret));
+    DPRINTF("RxBufAddr read val=0x%04x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val));
+    DPRINTF("RxBuf write val=0x%08x\n", val);
 
     s->RxBuf = val;
 
@@ -2575,14 +2599,14 @@ static uint32_t rtl8139_RxBuf_read(RTL8139State *s)
 {
     uint32_t ret = s->RxBuf;
 
-    DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret));
+    DPRINTF("RxBuf read val=0x%08x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val));
+    DPRINTF("IntrMask write(w) val=0x%04x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0x1e00, s->IntrMask);
@@ -2598,14 +2622,14 @@ static uint32_t rtl8139_IntrMask_read(RTL8139State *s)
 {
     uint32_t ret = s->IntrMask;
 
-    DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret));
+    DPRINTF("IntrMask read(w) val=0x%04x\n", ret);
 
     return ret;
 }
 
 static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val));
+    DPRINTF("IntrStatus write(w) val=0x%04x\n", val);
 
 #if 0
 
@@ -2642,7 +2666,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
 
     uint32_t ret = s->IntrStatus;
 
-    DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret));
+    DPRINTF("IntrStatus read(w) val=0x%04x\n", ret);
 
 #if 0
 
@@ -2658,7 +2682,7 @@ static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
 
 static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val)
 {
-    DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val));
+    DPRINTF("MultiIntr write(w) val=0x%04x\n", val);
 
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xf000, s->MultiIntr);
@@ -2670,7 +2694,7 @@ static uint32_t rtl8139_MultiIntr_read(RTL8139State *s)
 {
     uint32_t ret = s->MultiIntr;
 
-    DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret));
+    DPRINTF("MultiIntr read(w) val=0x%04x\n", ret);
 
     return ret;
 }
@@ -2718,11 +2742,12 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
             break;
         case MediaStatus:
             /* ignore */
-            DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus val=0x%02x\n", val));
+            DPRINTF("not implemented write(b) to MediaStatus val=0x%02x\n",
+                val);
             break;
 
         case HltClk:
-            DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val));
+            DPRINTF("HltClk write val=0x%08x\n", val);
             if (val == 'R')
             {
                 s->clock_enabled = 1;
@@ -2734,27 +2759,29 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
             break;
 
         case TxThresh:
-            DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val));
+            DPRINTF("C+ TxThresh write(b) val=0x%02x\n", val);
             s->TxThresh = val;
             break;
 
         case TxPoll:
-            DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val));
+            DPRINTF("C+ TxPoll write(b) val=0x%02x\n", val);
             if (val & (1 << 7))
             {
-                DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not implemented)\n"));
+                DPRINTF("C+ TxPoll high priority transmission (not "
+                    "implemented)\n");
                 //rtl8139_cplus_transmit(s);
             }
             if (val & (1 << 6))
             {
-                DEBUG_PRINT(("RTL8139C+ TxPoll normal priority transmission\n"));
+                DPRINTF("C+ TxPoll normal priority transmission\n");
                 rtl8139_cplus_transmit(s);
             }
 
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", addr, val));
+            DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr,
+                val);
             break;
     }
 }
@@ -2790,14 +2817,14 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
             rtl8139_BasicModeStatus_write(s, val);
             break;
         case NWayAdvert:
-            DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val));
+            DPRINTF("NWayAdvert write(w) val=0x%04x\n", val);
             s->NWayAdvert = val;
             break;
         case NWayLPAR:
-            DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val));
+            DPRINTF("forbidden NWayLPAR write(w) val=0x%04x\n", val);
             break;
         case NWayExpansion:
-            DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val));
+            DPRINTF("NWayExpansion write(w) val=0x%04x\n", val);
             s->NWayExpansion = val;
             break;
 
@@ -2810,7 +2837,8 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val));
+            DPRINTF("ioport write(w) addr=0x%x val=0x%04x via write(b)\n",
+                addr, val);
 
             rtl8139_io_writeb(opaque, addr, val & 0xff);
             rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
@@ -2823,7 +2851,7 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time)
     int64_t pci_time, next_time;
     uint32_t low_pci;
 
-    DEBUG_PRINT(("RTL8139: entered rtl8139_set_next_tctr_time\n"));
+    DPRINTF("entered rtl8139_set_next_tctr_time\n");
 
     if (s->TimerExpire && current_time >= s->TimerExpire) {
         s->IntrStatus |= PCSTimeout;
@@ -2867,7 +2895,7 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
     switch (addr)
     {
         case RxMissed:
-            DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n"));
+            DPRINTF("RxMissed clearing on write\n");
             s->RxMissed = 0;
             break;
 
@@ -2892,23 +2920,23 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
             break;
 
         case RxRingAddrLO:
-            DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", val));
+            DPRINTF("C+ RxRing low bits write val=0x%08x\n", val);
             s->RxRingAddrLO = val;
             break;
 
         case RxRingAddrHI:
-            DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", val));
+            DPRINTF("C+ RxRing high bits write val=0x%08x\n", val);
             s->RxRingAddrHI = val;
             break;
 
         case Timer:
-            DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
+            DPRINTF("TCTR Timer reset on write\n");
             s->TCTR_base = qemu_get_clock_ns(vm_clock);
             rtl8139_set_next_tctr_time(s, s->TCTR_base);
             break;
 
         case FlashReg:
-            DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val));
+            DPRINTF("FlashReg TimerInt write val=0x%08x\n", val);
             if (s->TimerInt != val) {
                 s->TimerInt = val;
                 rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
@@ -2916,7 +2944,8 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val));
+            DPRINTF("ioport write(l) addr=0x%x val=0x%08x via write(b)\n",
+                addr, val);
             rtl8139_io_writeb(opaque, addr, val & 0xff);
             rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
             rtl8139_io_writeb(opaque, addr + 2, (val >> 16) & 0xff);
@@ -2967,31 +2996,31 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
 
         case MediaStatus:
             ret = 0xd0;
-            DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret));
+            DPRINTF("MediaStatus read 0x%x\n", ret);
             break;
 
         case HltClk:
             ret = s->clock_enabled;
-            DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret));
+            DPRINTF("HltClk read 0x%x\n", ret);
             break;
 
         case PCIRevisionID:
             ret = RTL8139_PCI_REVID;
-            DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret));
+            DPRINTF("PCI Revision ID read 0x%x\n", ret);
             break;
 
         case TxThresh:
             ret = s->TxThresh;
-            DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret));
+            DPRINTF("C+ TxThresh read(b) val=0x%02x\n", ret);
             break;
 
         case 0x43: /* Part of TxConfig register. Windows driver tries to read it */
             ret = s->TxConfig >> 24;
-            DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret));
+            DPRINTF("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret);
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", addr));
+            DPRINTF("not implemented read(b) addr=0x%x\n", addr);
             ret = 0;
             break;
     }
@@ -3036,15 +3065,15 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
             break;
         case NWayAdvert:
             ret = s->NWayAdvert;
-            DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret));
+            DPRINTF("NWayAdvert read(w) val=0x%04x\n", ret);
             break;
         case NWayLPAR:
             ret = s->NWayLPAR;
-            DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret));
+            DPRINTF("NWayLPAR read(w) val=0x%04x\n", ret);
             break;
         case NWayExpansion:
             ret = s->NWayExpansion;
-            DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret));
+            DPRINTF("NWayExpansion read(w) val=0x%04x\n", ret);
             break;
 
         case CpCmd:
@@ -3064,12 +3093,12 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr));
+            DPRINTF("ioport read(w) addr=0x%x via read(b)\n", addr);
 
             ret  = rtl8139_io_readb(opaque, addr);
             ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
 
-            DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, ret));
+            DPRINTF("ioport read(w) addr=0x%x val=0x%04x\n", addr, ret);
             break;
     }
 
@@ -3088,7 +3117,7 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
         case RxMissed:
             ret = s->RxMissed;
 
-            DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret));
+            DPRINTF("RxMissed read val=0x%08x\n", ret);
             break;
 
         case TxConfig:
@@ -3113,34 +3142,34 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
 
         case RxRingAddrLO:
             ret = s->RxRingAddrLO;
-            DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret));
+            DPRINTF("C+ RxRing low bits read val=0x%08x\n", ret);
             break;
 
         case RxRingAddrHI:
             ret = s->RxRingAddrHI;
-            DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret));
+            DPRINTF("C+ RxRing high bits read val=0x%08x\n", ret);
             break;
 
         case Timer:
             ret = muldiv64(qemu_get_clock_ns(vm_clock) - s->TCTR_base,
                            PCI_FREQUENCY, get_ticks_per_sec());
-            DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
+            DPRINTF("TCTR Timer read val=0x%08x\n", ret);
             break;
 
         case FlashReg:
             ret = s->TimerInt;
-            DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret));
+            DPRINTF("FlashReg TimerInt read val=0x%08x\n", ret);
             break;
 
         default:
-            DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr));
+            DPRINTF("ioport read(l) addr=0x%x via read(b)\n", addr);
 
             ret  = rtl8139_io_readb(opaque, addr);
             ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
             ret |= rtl8139_io_readb(opaque, addr + 2) << 16;
             ret |= rtl8139_io_readb(opaque, addr + 3) << 24;
 
-            DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret));
+            DPRINTF("read(l) addr=0x%x val=%08x\n", addr, ret);
             break;
     }
 
@@ -3385,7 +3414,7 @@ static void rtl8139_timer(void *opaque)
 
     if (!s->clock_enabled)
     {
-        DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n"));
+        DPRINTF(">>> timer: clock is not running\n");
         return;
     }
 
commit afcd9c0dcd1d6ab14a72db6abde76142c6a0ac12
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Wed Apr 20 19:39:00 2011 -0400

    rtl8139: use TARGET_FMT_plx in debug messages
    
    Prevents a compilation failure when DEBUG_RTL8139 is defined:
    
    CC    libhw32/rtl8139.o
    cc1: warnings being treated as errors
    hw/rtl8139.c: In function ‘rtl8139_cplus_transmit_one’:
    hw/rtl8139.c:1960: error: format ‘%8lx’ expects type ‘long unsigned int’, but argument 5 has type ‘target_phys_addr_t’
    make[1]: *** [rtl8139.o] Error 1
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Cc: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 8790a00..a46416e 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -978,8 +978,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
         cplus_rx_ring_desc += 16 * descriptor;
 
-        DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n",
-               descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc));
+        DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from "
+                "host memory at %08x %08x = " TARGET_FMT_plx "\n", descriptor,
+                s->RxRingAddrHI, s->RxRingAddrLO, cplus_rx_ring_desc));
 
         uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
 
@@ -1957,8 +1958,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     /* Normal priority ring */
     cplus_tx_ring_desc += 16 * descriptor;
 
-    DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n",
-           descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
+    DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host "
+            "memory at %08x0x%08x = 0x" TARGET_FMT_plx "\n", descriptor,
+            s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
 
     uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
 
@@ -2069,8 +2071,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     /* append more data to the packet */
 
-    DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n",
-                 txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset));
+    DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host "
+            "memory at " TARGET_FMT_plx " to offset %d\n", txsize, tx_addr,
+            s->cplus_txbuffer_offset));
 
     cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
     s->cplus_txbuffer_offset += txsize;
commit 7cb4db8f41d20d2c9d9c9a6830a362eebaeb42ed
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Apr 20 11:19:15 2011 +0100

    linux-user/arm/nwfpe: rename REG_PC to ARM_REG_PC
    
    The REG_PC constant used in the ARM nwfpe code is fine in the kernel
    but when used in qemu can clash with a definition in the host system
    include files (in particular on Ubuntu Lucid SPARC, including signal.h
    will define a REG_PC). Rename the constant to avoid this issue.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
index 0a87c43..eebd93f 100644
--- a/linux-user/arm/nwfpe/fpa11.c
+++ b/linux-user/arm/nwfpe/fpa11.c
@@ -144,7 +144,7 @@ unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs)
 
 #if 0
   fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n",
-          opcode, qregs[REG_PC]);
+          opcode, qregs[ARM_REG_PC]);
 #endif
   fpa11 = GET_FPA11();
 
diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h
index f17647b..002b3cb 100644
--- a/linux-user/arm/nwfpe/fpa11.h
+++ b/linux-user/arm/nwfpe/fpa11.h
@@ -111,7 +111,7 @@ static inline void writeConditionCodes(unsigned int x)
         cpsr_write(user_registers,x,CPSR_NZCV);
 }
 
-#define REG_PC 15
+#define ARM_REG_PC 15
 
 unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs);
 
diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c
index b12e27d..3e7a938 100644
--- a/linux-user/arm/nwfpe/fpa11_cpdt.c
+++ b/linux-user/arm/nwfpe/fpa11_cpdt.c
@@ -220,7 +220,7 @@ static unsigned int PerformLDF(const unsigned int opcode)
    //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
 
    pBase = readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
+   if (ARM_REG_PC == getRn(opcode))
    {
      pBase += 8;
      write_back = 0;
@@ -256,7 +256,7 @@ static unsigned int PerformSTF(const unsigned int opcode)
    SetRoundingMode(ROUND_TO_NEAREST);
 
    pBase = readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
+   if (ARM_REG_PC == getRn(opcode))
    {
      pBase += 8;
      write_back = 0;
@@ -289,7 +289,7 @@ static unsigned int PerformLFM(const unsigned int opcode)
    target_ulong pBase, pAddress, pFinal;
 
    pBase = readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
+   if (ARM_REG_PC == getRn(opcode))
    {
      pBase += 8;
      write_back = 0;
@@ -322,7 +322,7 @@ static unsigned int PerformSFM(const unsigned int opcode)
    target_ulong pBase, pAddress, pFinal;
 
    pBase = readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
+   if (ARM_REG_PC == getRn(opcode))
    {
      pBase += 8;
      write_back = 0;
commit f2dd89d0c7e5d39237f43392ccaed79bda47a71e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 18 19:07:12 2011 +0100

    target-arm: Handle UNDEF cases for Neon VLD/VST multiple-structures
    
    Correctly UNDEF for Neon VLD/VST "multiple structures" forms where the
    align field is not valid.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 80b25ac..8b309d4 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3830,6 +3830,21 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
         size = (insn >> 6) & 3;
         if (op > 10)
             return 1;
+        /* Catch UNDEF cases for bad values of align field */
+        switch (op & 0xc) {
+        case 4:
+            if (((insn >> 5) & 1) == 1) {
+                return 1;
+            }
+            break;
+        case 8:
+            if (((insn >> 4) & 3) == 3) {
+                return 1;
+            }
+            break;
+        default:
+            break;
+        }
         nregs = neon_ls_element_type[op].nregs;
         interleave = neon_ls_element_type[op].interleave;
         spacing = neon_ls_element_type[op].spacing;
commit 93262b1625ecb9c6ff22d5a51f38e312b5b7725a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 18 19:07:11 2011 +0100

    target-arm: Handle UNDEFs for Neon single element load/stores
    
    Handle the UNDEF and UNPREDICTABLE cases for Neon "single element to
    one lane" VLD and "single element from one lane" VST.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index e1bda57..80b25ac 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3975,6 +3975,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
             stride = (1 << size) * nregs;
         } else {
             /* Single element.  */
+            int idx = (insn >> 4) & 0xf;
             pass = (insn >> 7) & 1;
             switch (size) {
             case 0:
@@ -3993,6 +3994,39 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 abort();
             }
             nregs = ((insn >> 8) & 3) + 1;
+            /* Catch the UNDEF cases. This is unavoidably a bit messy. */
+            switch (nregs) {
+            case 1:
+                if (((idx & (1 << size)) != 0) ||
+                    (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
+                    return 1;
+                }
+                break;
+            case 3:
+                if ((idx & 1) != 0) {
+                    return 1;
+                }
+                /* fall through */
+            case 2:
+                if (size == 2 && (idx & 2) != 0) {
+                    return 1;
+                }
+                break;
+            case 4:
+                if ((size == 2) && ((idx & 3) == 3)) {
+                    return 1;
+                }
+                break;
+            default:
+                abort();
+            }
+            if ((rd + stride * (nregs - 1)) > 31) {
+                /* Attempts to write off the end of the register file
+                 * are UNPREDICTABLE; we choose to UNDEF because otherwise
+                 * the neon_load_reg() would write off the end of the array.
+                 */
+                return 1;
+            }
             addr = tcg_temp_new_i32();
             load_reg_var(s, addr, rn);
             for (reg = 0; reg < nregs; reg++) {
commit dbf352ad6e55dc7b40c62b402289164265a4f17c
Merge: 347ac8e... 36d8d02...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 25 10:26:10 2011 -0500

    Merge remote-tracking branch 'awilliam/ipxe' into staging

commit 347ac8e35661eff1c2b5ec74d11ee152f2a61856
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: switch to softfloat
    
    This increase the correctness (precision, NaN values, corner cases) on
    non-x86 machines, and add the possibility to handle the exception
    correctly.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index da2da04..f2eab30 100755
--- a/configure
+++ b/configure
@@ -3275,14 +3275,7 @@ if test ! -z "$gdb_xml_files" ; then
   echo "TARGET_XML_FILES=$list" >> $config_target_mak
 fi
 
-case "$target_arch2" in
-  i386|x86_64)
-    echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
-    ;;
-  *)
-    echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
-    ;;
-esac
+echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
 
 if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
   echo "TARGET_HAS_BFLT=y" >> $config_target_mak
commit a1d8db07fb46e1da410ca7b4ce24a997707d4a53
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix constants wrt softfloat
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 292e0de..ee36a71 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -124,6 +124,10 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_is_any_nan floatx80_is_any_nan
 #define floatx_is_neg floatx80_is_neg
 #define floatx_is_zero floatx80_is_zero
+#define floatx_zero floatx80_zero
+#define floatx_one floatx80_one
+#define floatx_ln2 floatx80_ln2
+#define floatx_pi floatx80_pi
 #else
 #define floatx_to_int32 float64_to_int32
 #define floatx_to_int64 float64_to_int64
@@ -149,6 +153,10 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_is_any_nan float64_is_any_nan
 #define floatx_is_neg float64_is_neg
 #define floatx_is_zero float64_is_zero
+#define floatx_zero float64_zero
+#define floatx_one float64_one
+#define floatx_ln2 float64_ln2
+#define floatx_pi float64_pi
 #endif
 
 #define RC_MASK         0xc00
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 334f130..3c539f3 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -95,15 +95,25 @@ static const uint8_t rclb_table[32] = {
     6, 7, 8, 0, 1, 2, 3, 4,
 };
 
+#if defined(CONFIG_SOFTFLOAT)
+# define floatx_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
+# define floatx_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
+# define floatx_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
+#else
+# define floatx_lg2 (0.30102999566398119523L)
+# define floatx_l2e (1.44269504088896340739L)
+# define floatx_l2t (3.32192809488736234781L)
+#endif
+
 static const CPU86_LDouble f15rk[7] =
 {
-    0.00000000000000000000L,
-    1.00000000000000000000L,
-    3.14159265358979323851L,  /*pi*/
-    0.30102999566398119523L,  /*lg2*/
-    0.69314718055994530943L,  /*ln2*/
-    1.44269504088896340739L,  /*l2e*/
-    3.32192809488736234781L,  /*l2t*/
+    floatx_zero,
+    floatx_one,
+    floatx_pi,
+    floatx_lg2,
+    floatx_ln2,
+    floatx_l2e,
+    floatx_l2t,
 };
 
 /* broken thread support */
commit bcb5fec5af5d543f6ea0efa513c00503a2ada5b6
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fprem() and helper_fprem1() wrt softfloat
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index fd9d8d3..334f130 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4053,21 +4053,24 @@ void helper_fxtract(void)
 
 void helper_fprem1(void)
 {
-    CPU86_LDouble dblq, fpsrcop, fptemp;
+    double st0, st1, dblq, fpsrcop, fptemp;
     CPU86_LDoubleU fpsrcop1, fptemp1;
     int expdif;
     signed long long int q;
 
-    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
-        ST0 = 0.0 / 0.0; /* NaN */
+    st0 = CPU86_LDouble_to_double(ST0);
+    st1 = CPU86_LDouble_to_double(ST1);
+
+    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+        ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
         return;
     }
 
-    fpsrcop = ST0;
-    fptemp = ST1;
-    fpsrcop1.d = fpsrcop;
-    fptemp1.d = fptemp;
+    fpsrcop = st0;
+    fptemp = st1;
+    fpsrcop1.d = ST0;
+    fptemp1.d = ST1;
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
 
     if (expdif < 0) {
@@ -4081,7 +4084,7 @@ void helper_fprem1(void)
         dblq = fpsrcop / fptemp;
         /* round dblq towards nearest integer */
         dblq = rint(dblq);
-        ST0 = fpsrcop - fptemp * dblq;
+        st0 = fpsrcop - fptemp * dblq;
 
         /* convert dblq to q by truncating towards zero */
         if (dblq < 0.0)
@@ -4097,31 +4100,35 @@ void helper_fprem1(void)
     } else {
         env->fpus |= 0x400;  /* C2 <-- 1 */
         fptemp = pow(2.0, expdif - 50);
-        fpsrcop = (ST0 / ST1) / fptemp;
+        fpsrcop = (st0 / st1) / fptemp;
         /* fpsrcop = integer obtained by chopping */
         fpsrcop = (fpsrcop < 0.0) ?
                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
-        ST0 -= (ST1 * fpsrcop * fptemp);
+        st0 -= (st1 * fpsrcop * fptemp);
     }
+    ST0 = double_to_CPU86_LDouble(st0);
 }
 
 void helper_fprem(void)
 {
-    CPU86_LDouble dblq, fpsrcop, fptemp;
+    double st0, st1, dblq, fpsrcop, fptemp;
     CPU86_LDoubleU fpsrcop1, fptemp1;
     int expdif;
     signed long long int q;
 
-    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
-       ST0 = 0.0 / 0.0; /* NaN */
+    st0 = CPU86_LDouble_to_double(ST0);
+    st1 = CPU86_LDouble_to_double(ST1);
+
+    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+       ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
        return;
     }
 
-    fpsrcop = (CPU86_LDouble)ST0;
-    fptemp = (CPU86_LDouble)ST1;
-    fpsrcop1.d = fpsrcop;
-    fptemp1.d = fptemp;
+    fpsrcop = st0;
+    fptemp = st1;
+    fpsrcop1.d = ST0;
+    fptemp1.d = ST1;
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
 
     if (expdif < 0) {
@@ -4135,7 +4142,7 @@ void helper_fprem(void)
         dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
         /* round dblq towards zero */
         dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
-        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
+        st0 = fpsrcop/*ST0*/ - fptemp * dblq;
 
         /* convert dblq to q by truncating towards zero */
         if (dblq < 0.0)
@@ -4152,12 +4159,13 @@ void helper_fprem(void)
         int N = 32 + (expdif % 32); /* as per AMD docs */
         env->fpus |= 0x400;  /* C2 <-- 1 */
         fptemp = pow(2.0, (double)(expdif - N));
-        fpsrcop = (ST0 / ST1) / fptemp;
+        fpsrcop = (st0 / st1) / fptemp;
         /* fpsrcop = integer obtained by chopping */
         fpsrcop = (fpsrcop < 0.0) ?
                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
-        ST0 -= (ST1 * fpsrcop * fptemp);
+        st0 -= (st1 * fpsrcop * fptemp);
     }
+    ST0 = double_to_CPU86_LDouble(st0);
 }
 
 void helper_fyl2xp1(void)
commit a2c9ed3cbfde4ce521b6b9672afc4fd8cf67ab8e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix logarithmic and trigonometric helpers wrt softfloat
    
    Use the new CPU86_LDouble <-> double conversion functions to make logarithmic
    and trigonometric helpers working with softfloat.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 64c0bbf..fd9d8d3 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -17,6 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <math.h>
 #include "exec.h"
 #include "exec-all.h"
 #include "host-utils.h"
@@ -3981,17 +3982,19 @@ void helper_fbst_ST0(target_ulong ptr)
 
 void helper_f2xm1(void)
 {
-    ST0 = pow(2.0,ST0) - 1.0;
+    double val = CPU86_LDouble_to_double(ST0);
+    val = pow(2.0, val) - 1.0;
+    ST0 = double_to_CPU86_LDouble(val);
 }
 
 void helper_fyl2x(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if (fptemp>0.0){
-        fptemp = log(fptemp)/log(2.0);	 /* log2(ST) */
-        ST1 *= fptemp;
+        fptemp = log(fptemp)/log(2.0);    /* log2(ST) */
+        fptemp *= CPU86_LDouble_to_double(ST1);
+        ST1 = double_to_CPU86_LDouble(fptemp);
         fpop();
     } else {
         env->fpus &= (~0x4700);
@@ -4001,15 +4004,15 @@ void helper_fyl2x(void)
 
 void helper_fptan(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
         env->fpus |= 0x400;
     } else {
-        ST0 = tan(fptemp);
+        fptemp = tan(fptemp);
+        ST0 = double_to_CPU86_LDouble(fptemp);
         fpush();
-        ST0 = 1.0;
+        ST0 = floatx_one;
         env->fpus &= (~0x400);  /* C2 <-- 0 */
         /* the above code is for  |arg| < 2**52 only */
     }
@@ -4017,11 +4020,11 @@ void helper_fptan(void)
 
 void helper_fpatan(void)
 {
-    CPU86_LDouble fptemp, fpsrcop;
+    double fptemp, fpsrcop;
 
-    fpsrcop = ST1;
-    fptemp = ST0;
-    ST1 = atan2(fpsrcop,fptemp);
+    fpsrcop = CPU86_LDouble_to_double(ST1);
+    fptemp = CPU86_LDouble_to_double(ST0);
+    ST1 = double_to_CPU86_LDouble(atan2(fpsrcop, fptemp));
     fpop();
 }
 
@@ -4159,12 +4162,12 @@ void helper_fprem(void)
 
 void helper_fyl2xp1(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if ((fptemp+1.0)>0.0) {
         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
-        ST1 *= fptemp;
+        fptemp *= CPU86_LDouble_to_double(ST1);
+        ST1 = double_to_CPU86_LDouble(fptemp);
         fpop();
     } else {
         env->fpus &= (~0x4700);
@@ -4183,15 +4186,14 @@ void helper_fsqrt(void)
 
 void helper_fsincos(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
         env->fpus |= 0x400;
     } else {
-        ST0 = sin(fptemp);
+        ST0 = double_to_CPU86_LDouble(sin(fptemp));
         fpush();
-        ST0 = cos(fptemp);
+        ST0 = double_to_CPU86_LDouble(cos(fptemp));
         env->fpus &= (~0x400);  /* C2 <-- 0 */
         /* the above code is for  |arg| < 2**63 only */
     }
@@ -4214,13 +4216,12 @@ void helper_fscale(void)
 
 void helper_fsin(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
         env->fpus |= 0x400;
     } else {
-        ST0 = sin(fptemp);
+        ST0 = double_to_CPU86_LDouble(sin(fptemp));
         env->fpus &= (~0x400);  /* C2 <-- 0 */
         /* the above code is for  |arg| < 2**53 only */
     }
@@ -4228,13 +4229,12 @@ void helper_fsin(void)
 
 void helper_fcos(void)
 {
-    CPU86_LDouble fptemp;
+    double fptemp = CPU86_LDouble_to_double(ST0);
 
-    fptemp = ST0;
     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
         env->fpus |= 0x400;
     } else {
-        ST0 = cos(fptemp);
+        ST0 = double_to_CPU86_LDouble(cos(fptemp));
         env->fpus &= (~0x400);  /* C2 <-- 0 */
         /* the above code is for  |arg5 < 2**63 only */
     }
commit 47c0143cdde080101e97a1b39f3ff13e33b5726c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: add CPU86_LDouble <-> double conversion functions
    
    Add functions to convert CPU86_LDouble to double and vice versa. They
    are going to be used to implement logarithmic and trigonometric function
    until softfloat implement them.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index f7cdaaa..64c0bbf 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3431,6 +3431,28 @@ void helper_verw(target_ulong selector1)
 
 /* x87 FPU helpers */
 
+static inline double CPU86_LDouble_to_double(CPU86_LDouble a)
+{
+    union {
+        float64 f64;
+        double d;
+    } u;
+
+    u.f64 = floatx_to_float64(a, &env->fp_status);
+    return u.d;
+}
+
+static inline CPU86_LDouble double_to_CPU86_LDouble(double a)
+{
+    union {
+        float64 f64;
+        double d;
+    } u;
+
+    u.d = a;
+    return float64_to_floatx(u.f64, &env->fp_status);
+}
+
 static void fpu_set_exception(int mask)
 {
     env->fpus |= mask;
commit c2ef9a83be8a176802c33db7f826ff30a18b50f3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: replace approx_rsqrt and approx_rcp by softfloat ops
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 589a68b..f7cdaaa 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4794,16 +4794,6 @@ void helper_boundl(target_ulong a0, int v)
     }
 }
 
-static float approx_rsqrt(float a)
-{
-    return 1.0 / sqrt(a);
-}
-
-static float approx_rcp(float a)
-{
-    return 1.0 / a;
-}
-
 #if !defined(CONFIG_USER_ONLY)
 
 #define MMUSUFFIX _mmu
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index ac0f150..703be99 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -778,28 +778,38 @@ int64_t helper_cvttsd2sq(XMMReg *s)
 
 void helper_rsqrtps(XMMReg *d, XMMReg *s)
 {
-    d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
-    d->XMM_S(1) = approx_rsqrt(s->XMM_S(1));
-    d->XMM_S(2) = approx_rsqrt(s->XMM_S(2));
-    d->XMM_S(3) = approx_rsqrt(s->XMM_S(3));
+    d->XMM_S(0) = float32_div(float32_one,
+                              float32_sqrt(s->XMM_S(0), &env->sse_status),
+                              &env->sse_status);
+    d->XMM_S(1) = float32_div(float32_one,
+                              float32_sqrt(s->XMM_S(1), &env->sse_status),
+                              &env->sse_status);
+    d->XMM_S(2) = float32_div(float32_one,
+                              float32_sqrt(s->XMM_S(2), &env->sse_status),
+                              &env->sse_status);
+    d->XMM_S(3) = float32_div(float32_one,
+                              float32_sqrt(s->XMM_S(3), &env->sse_status),
+                              &env->sse_status);
 }
 
 void helper_rsqrtss(XMMReg *d, XMMReg *s)
 {
-    d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
+    d->XMM_S(0) = float32_div(float32_one,
+                              float32_sqrt(s->XMM_S(0), &env->sse_status),
+                              &env->sse_status);
 }
 
 void helper_rcpps(XMMReg *d, XMMReg *s)
 {
-    d->XMM_S(0) = approx_rcp(s->XMM_S(0));
-    d->XMM_S(1) = approx_rcp(s->XMM_S(1));
-    d->XMM_S(2) = approx_rcp(s->XMM_S(2));
-    d->XMM_S(3) = approx_rcp(s->XMM_S(3));
+    d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
+    d->XMM_S(1) = float32_div(float32_one, s->XMM_S(1), &env->sse_status);
+    d->XMM_S(2) = float32_div(float32_one, s->XMM_S(2), &env->sse_status);
+    d->XMM_S(3) = float32_div(float32_one, s->XMM_S(3), &env->sse_status);
 }
 
 void helper_rcpss(XMMReg *d, XMMReg *s)
 {
-    d->XMM_S(0) = approx_rcp(s->XMM_S(0));
+    d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
 }
 
 static inline uint64_t helper_extrq(uint64_t src, int shift, int len)
@@ -1272,14 +1282,16 @@ void helper_pfpnacc(MMXReg *d, MMXReg *s)
 
 void helper_pfrcp(MMXReg *d, MMXReg *s)
 {
-    d->MMX_S(0) = approx_rcp(s->MMX_S(0));
+    d->MMX_S(0) = float32_div(float32_one, s->MMX_S(0), &env->mmx_status);
     d->MMX_S(1) = d->MMX_S(0);
 }
 
 void helper_pfrsqrt(MMXReg *d, MMXReg *s)
 {
     d->MMX_L(1) = s->MMX_L(0) & 0x7fffffff;
-    d->MMX_S(1) = approx_rsqrt(d->MMX_S(1));
+    d->MMX_S(1) = float32_div(float32_one,
+                              float32_sqrt(d->MMX_S(1), &env->mmx_status),
+                              &env->mmx_status);
     d->MMX_L(1) |= s->MMX_L(0) & 0x80000000;
     d->MMX_L(0) = d->MMX_L(1);
 }
commit fec05e429943a2486ebe4c65da7b46a90f2dcfb2
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fsqrt() wrt softfloat
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index b2af894..292e0de 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -114,6 +114,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_div floatx80_div
 #define floatx_mul floatx80_mul
 #define floatx_sub floatx80_sub
+#define floatx_sqrt floatx80_sqrt
 #define floatx_abs floatx80_abs
 #define floatx_chs floatx80_chs
 #define floatx_scalbn floatx80_scalbn
@@ -121,6 +122,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_compare floatx80_compare
 #define floatx_compare_quiet floatx80_compare_quiet
 #define floatx_is_any_nan floatx80_is_any_nan
+#define floatx_is_neg floatx80_is_neg
 #define floatx_is_zero floatx80_is_zero
 #else
 #define floatx_to_int32 float64_to_int32
@@ -137,6 +139,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_div float64_div
 #define floatx_mul float64_mul
 #define floatx_sub float64_sub
+#define floatx_sqrt float64_sqrt
 #define floatx_abs float64_abs
 #define floatx_chs float64_chs
 #define floatx_scalbn float64_scalbn
@@ -144,6 +147,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_compare float64_compare
 #define floatx_compare_quiet float64_compare_quiet
 #define floatx_is_any_nan float64_is_any_nan
+#define floatx_is_neg float64_is_neg
 #define floatx_is_zero float64_is_zero
 #endif
 
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index bd24d8c..589a68b 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4152,14 +4152,11 @@ void helper_fyl2xp1(void)
 
 void helper_fsqrt(void)
 {
-    CPU86_LDouble fptemp;
-
-    fptemp = ST0;
-    if (fptemp<0.0) {
+    if (floatx_is_neg(ST0)) {
         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
         env->fpus |= 0x400;
     }
-    ST0 = sqrt(fptemp);
+    ST0 = floatx_sqrt(ST0, &env->fp_status);
 }
 
 void helper_fsincos(void)
commit 13822781d4732f847555a2f60560c71c531c9f98
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fdiv() wrt softfloat
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 211cc8c..b2af894 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -111,6 +111,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_to_float32 floatx80_to_float32
 #define floatx_to_float64 floatx80_to_float64
 #define floatx_add floatx80_add
+#define floatx_div floatx80_div
 #define floatx_mul floatx80_mul
 #define floatx_sub floatx80_sub
 #define floatx_abs floatx80_abs
@@ -120,6 +121,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_compare floatx80_compare
 #define floatx_compare_quiet floatx80_compare_quiet
 #define floatx_is_any_nan floatx80_is_any_nan
+#define floatx_is_zero floatx80_is_zero
 #else
 #define floatx_to_int32 float64_to_int32
 #define floatx_to_int64 float64_to_int64
@@ -132,6 +134,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_to_float32 float64_to_float32
 #define floatx_to_float64(x, e) (x)
 #define floatx_add float64_add
+#define floatx_div float64_div
 #define floatx_mul float64_mul
 #define floatx_sub float64_sub
 #define floatx_abs float64_abs
@@ -141,6 +144,7 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_compare float64_compare
 #define floatx_compare_quiet float64_compare_quiet
 #define floatx_is_any_nan float64_is_any_nan
+#define floatx_is_zero float64_is_zero
 #endif
 
 #define RC_MASK         0xc00
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 4850c63..bd24d8c 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3440,9 +3440,10 @@ static void fpu_set_exception(int mask)
 
 static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
 {
-    if (b == 0.0)
+    if (floatx_is_zero(b)) {
         fpu_set_exception(FPUS_ZE);
-    return a / b;
+    }
+    return floatx_div(a, b, &env->fp_status);
 }
 
 static void fpu_raise_exception(void)
commit c9ad19c57b4e35dda507ec636443069048a4ad72
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fxtract() wrt softfloat
    
    With softfloat it's not possible to play with the overflow of an
    unsigned value to get the 0 case partially correct. Use a special case
    for that. Using a division to generate an infinity is the easiest way
    that works for both softfloat and softfloat-native.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 943d217..4850c63 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4005,15 +4005,24 @@ void helper_fpatan(void)
 void helper_fxtract(void)
 {
     CPU86_LDoubleU temp;
-    unsigned int expdif;
 
     temp.d = ST0;
-    expdif = EXPD(temp) - EXPBIAS;
-    /*DP exponent bias*/
-    ST0 = expdif;
-    fpush();
-    BIASEXPONENT(temp);
-    ST0 = temp.d;
+
+    if (floatx_is_zero(ST0)) {
+        /* Easy way to generate -inf and raising division by 0 exception */
+        ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status);
+        fpush();
+        ST0 = temp.d;
+    } else {
+        int expdif;
+
+        expdif = EXPD(temp) - EXPBIAS;
+        /*DP exponent bias*/
+        ST0 = int32_to_floatx(expdif, &env->fp_status);
+        fpush();
+        BIASEXPONENT(temp);
+        ST0 = temp.d;
+    }
 }
 
 void helper_fprem1(void)
commit 788e733664aab69e65bf5d5d228767cf4371f3ab
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fbld_ST0() wrt softfloat
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index dce28fa..943d217 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3920,9 +3920,10 @@ void helper_fbld_ST0(target_ulong ptr)
         v = ldub(ptr + i);
         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
     }
-    tmp = val;
-    if (ldub(ptr + 9) & 0x80)
-        tmp = -tmp;
+    tmp = int64_to_floatx(val, &env->fp_status);
+    if (ldub(ptr + 9) & 0x80) {
+        floatx_chs(tmp);
+    }
     fpush();
     ST0 = tmp;
 }
commit be1c17c7fdc16d9cb88f4092f23a494b942b68d7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    target-i386: fix helper_fscale() wrt softfloat
    
    Use the scalbn softfloat function to implement helper_fscale(). This
    fixes corner cases (e.g. NaN) and makes a few more GNU libc math tests
    to pass.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index ae6b947..211cc8c 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -115,9 +115,11 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_sub floatx80_sub
 #define floatx_abs floatx80_abs
 #define floatx_chs floatx80_chs
+#define floatx_scalbn floatx80_scalbn
 #define floatx_round_to_int floatx80_round_to_int
 #define floatx_compare floatx80_compare
 #define floatx_compare_quiet floatx80_compare_quiet
+#define floatx_is_any_nan floatx80_is_any_nan
 #else
 #define floatx_to_int32 float64_to_int32
 #define floatx_to_int64 float64_to_int64
@@ -134,9 +136,11 @@ static inline void svm_check_intercept(uint32_t type)
 #define floatx_sub float64_sub
 #define floatx_abs float64_abs
 #define floatx_chs float64_chs
+#define floatx_scalbn float64_scalbn
 #define floatx_round_to_int float64_round_to_int
 #define floatx_compare float64_compare
 #define floatx_compare_quiet float64_compare_quiet
+#define floatx_is_any_nan float64_is_any_nan
 #endif
 
 #define RC_MASK         0xc00
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index fba536f..dce28fa 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4174,7 +4174,12 @@ void helper_frndint(void)
 
 void helper_fscale(void)
 {
-    ST0 = ldexp (ST0, (int)(ST1));
+    if (floatx_is_any_nan(ST1)) {
+        ST0 = ST1;
+    } else {
+        int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status);
+        ST0 = floatx_scalbn(ST0, n, &env->fp_status);
+    }
 }
 
 void helper_fsin(void)
commit 4cc5383f807a7d70942de51326a8dddad7331fa5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    softfloat-native: add float*_is_any_nan() functions
    
    Add float*_is_any_nan() functions to match the softfloat API.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c
index 50355a4..8848651 100644
--- a/fpu/softfloat-native.c
+++ b/fpu/softfloat-native.c
@@ -263,6 +263,15 @@ int float32_is_quiet_nan( float32 a1 )
     return ( 0xFF800000 < ( a<<1 ) );
 }
 
+int float32_is_any_nan( float32 a1 )
+{
+    float32u u;
+    uint32_t a;
+    u.f = a1;
+    a = u.i;
+    return (a & ~(1 << 31)) > 0x7f800000U;
+}
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
@@ -422,6 +431,16 @@ int float64_is_quiet_nan( float64 a1 )
 
 }
 
+int float64_is_any_nan( float64 a1 )
+{
+    float64u u;
+    uint64_t a;
+    u.f = a1;
+    a = u.i;
+
+    return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 );
+}
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -511,4 +530,11 @@ int floatx80_is_quiet_nan( floatx80 a1 )
     return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 );
 }
 
+int floatx80_is_any_nan( floatx80 a1 )
+{
+    floatx80u u;
+    u.f = a1;
+    return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 );
+}
+
 #endif
diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index f497e64..6afb74a 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -255,6 +255,7 @@ int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
 int float32_is_signaling_nan( float32 );
 int float32_is_quiet_nan( float32 );
+int float32_is_any_nan( float32 );
 
 INLINE float32 float32_abs(float32 a)
 {
@@ -375,6 +376,7 @@ INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM)
 int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
 int float64_is_signaling_nan( float64 );
+int float64_is_any_nan( float64 );
 int float64_is_quiet_nan( float64 );
 
 INLINE float64 float64_abs(float64 a)
@@ -492,6 +494,7 @@ int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
 int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_is_signaling_nan( floatx80 );
 int floatx80_is_quiet_nan( floatx80 );
+int floatx80_is_any_nan( floatx80 );
 
 INLINE floatx80 floatx80_abs(floatx80 a)
 {
commit d6882cf01fd9e3e1c9dee38ff7dae0d8d377c8f7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:23 2011 +0200

    softfloat-native: fix float*_scalbn() functions
    
    float*_scalbn() should be able to take a status parameter. Fix that.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 97fb3c7..f497e64 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -283,7 +283,7 @@ INLINE float32 float32_is_zero(float32 a)
     return fpclassify(a) == FP_ZERO;
 }
 
-INLINE float32 float32_scalbn(float32 a, int n)
+INLINE float32 float32_scalbn(float32 a, int n STATUS_PARAM)
 {
     return scalbnf(a, n);
 }
@@ -404,7 +404,7 @@ INLINE float64 float64_is_zero(float64 a)
     return fpclassify(a) == FP_ZERO;
 }
 
-INLINE float64 float64_scalbn(float64 a, int n)
+INLINE float64 float64_scalbn(float64 a, int n STATUS_PARAM)
 {
     return scalbn(a, n);
 }
@@ -520,7 +520,7 @@ INLINE floatx80 floatx80_is_zero(floatx80 a)
     return fpclassify(a) == FP_ZERO;
 }
 
-INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
+INLINE floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM)
 {
     return scalbnl(a, n);
 }
commit 326b9e98a391d542cc33c4c91782ff4ba51edfc5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: fix float*_scalnb() corner cases
    
    float*_scalnb() were not taking into account all cases. This patch fixes
    some corner cases:
    - NaN values in input were not properly propagated and the invalid flag
      not correctly raised. Use propagateFloat*NaN() for that.
    - NaN or infinite values in input of floatx80_scalnb() were not correctly
      detected due to a typo.
    - The sum of exponent and n could overflow, leading to strange results.
      Additionally having int16 defined to int make that happening for a very
      small range of values. Fix that by saturating n to the maximum exponent
      range, and using an explicit wider type if needed.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 4368069..baba1dc 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6333,7 +6333,7 @@ MINMAX(64, 0x7ff)
 float32 float32_scalbn( float32 a, int n STATUS_PARAM )
 {
     flag aSign;
-    int16 aExp;
+    int16_t aExp;
     uint32_t aSig;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
@@ -6342,6 +6342,9 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
     aSign = extractFloat32Sign( a );
 
     if ( aExp == 0xFF ) {
+        if ( aSig ) {
+            return propagateFloat32NaN( a, a STATUS_VAR );
+        }
         return a;
     }
     if ( aExp != 0 )
@@ -6349,6 +6352,12 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
     else if ( aSig == 0 )
         return a;
 
+    if (n > 0x200) {
+        n = 0x200;
+    } else if (n < -0x200) {
+        n = -0x200;
+    }
+
     aExp += n - 1;
     aSig <<= 7;
     return normalizeRoundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
@@ -6357,7 +6366,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
 float64 float64_scalbn( float64 a, int n STATUS_PARAM )
 {
     flag aSign;
-    int16 aExp;
+    int16_t aExp;
     uint64_t aSig;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
@@ -6366,6 +6375,9 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
     aSign = extractFloat64Sign( a );
 
     if ( aExp == 0x7FF ) {
+        if ( aSig ) {
+            return propagateFloat64NaN( a, a STATUS_VAR );
+        }
         return a;
     }
     if ( aExp != 0 )
@@ -6373,6 +6385,12 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
     else if ( aSig == 0 )
         return a;
 
+    if (n > 0x1000) {
+        n = 0x1000;
+    } else if (n < -0x1000) {
+        n = -0x1000;
+    }
+
     aExp += n - 1;
     aSig <<= 10;
     return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
@@ -6382,19 +6400,29 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
 floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
 {
     flag aSign;
-    int16 aExp;
+    int32_t aExp;
     uint64_t aSig;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
 
-    if ( aExp == 0x7FF ) {
+    if ( aExp == 0x7FFF ) {
+        if ( aSig<<1 ) {
+            return propagateFloatx80NaN( a, a STATUS_VAR );
+        }
         return a;
     }
+
     if (aExp == 0 && aSig == 0)
         return a;
 
+    if (n > 0x10000) {
+        n = 0x10000;
+    } else if (n < -0x10000) {
+        n = -0x10000;
+    }
+
     aExp += n;
     return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
                                           aSign, aExp, aSig, 0 STATUS_VAR );
@@ -6405,7 +6433,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
 float128 float128_scalbn( float128 a, int n STATUS_PARAM )
 {
     flag aSign;
-    int32 aExp;
+    int32_t aExp;
     uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
@@ -6413,6 +6441,9 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
     aExp = extractFloat128Exp( a );
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) {
+            return propagateFloat128NaN( a, a STATUS_VAR );
+        }
         return a;
     }
     if ( aExp != 0 )
@@ -6420,6 +6451,12 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
     else if ( aSig0 == 0 && aSig1 == 0 )
         return a;
 
+    if (n > 0x10000) {
+        n = 0x10000;
+    } else if (n < -0x10000) {
+        n = -0x10000;
+    }
+
     aExp += n - 1;
     return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
                                           STATUS_VAR );
commit f6714d365da068481d83787b4044134ae2ec5dfd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: add floatx80_compare*() functions
    
    Add floatx80_compare() and floatx80_compare_quiet() functions to match
    the softfloat-native ones.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6ce0b61..4368069 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6190,6 +6190,52 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM )  \
 COMPARE(32, 0xff)
 COMPARE(64, 0x7ff)
 
+INLINE int floatx80_compare_internal( floatx80 a, floatx80 b,
+                                      int is_quiet STATUS_PARAM )
+{
+    flag aSign, bSign;
+
+    if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
+          ( extractFloatx80Frac( a )<<1 ) ) ||
+        ( ( extractFloatx80Exp( b ) == 0x7fff ) &&
+          ( extractFloatx80Frac( b )<<1 ) )) {
+        if (!is_quiet ||
+            floatx80_is_signaling_nan( a ) ||
+            floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
+        return float_relation_unordered;
+    }
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign != bSign ) {
+
+        if ( ( ( (uint16_t) ( ( a.high | b.high ) << 1 ) ) == 0) &&
+             ( ( a.low | b.low ) == 0 ) ) {
+            /* zero case */
+            return float_relation_equal;
+        } else {
+            return 1 - (2 * aSign);
+        }
+    } else {
+        if (a.low == b.low && a.high == b.high) {
+            return float_relation_equal;
+        } else {
+            return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
+        }
+    }
+}
+
+int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
+{
+    return floatx80_compare_internal(a, b, 0 STATUS_VAR);
+}
+
+int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+{
+    return floatx80_compare_internal(a, b, 1 STATUS_VAR);
+}
+
 INLINE int float128_compare_internal( float128 a, float128 b,
                                       int is_quiet STATUS_PARAM )
 {
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 7b3b88f..5eff085 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -550,6 +550,8 @@ int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_is_quiet_nan( floatx80 );
 int floatx80_is_signaling_nan( floatx80 );
 floatx80 floatx80_maybe_silence_nan( floatx80 );
commit d2b1027d5ffe7c6832bd50f167751171ed168ed0
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat-native: add a few constant values
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index ea7a15e..97fb3c7 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -172,6 +172,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM);
 #endif
 
 /*----------------------------------------------------------------------------
+| Software IEC/IEEE single-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float32_zero (0.0)
+#define float32_one (1.0)
+#define float32_ln2 (0.6931471)
+#define float32_pi (3.1415926)
+#define float32_half (0.5)
+
+/*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int float32_to_int32( float32  STATUS_PARAM);
@@ -280,6 +289,15 @@ INLINE float32 float32_scalbn(float32 a, int n)
 }
 
 /*----------------------------------------------------------------------------
+| Software IEC/IEEE double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float64_zero (0.0)
+#define float64_one (1.0)
+#define float64_ln2 (0.693147180559945)
+#define float64_pi (3.141592653589793)
+#define float64_half (0.5)
+
+/*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int float64_to_int32( float64 STATUS_PARAM );
@@ -394,6 +412,15 @@ INLINE float64 float64_scalbn(float64 a, int n)
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define floatx80_zero (0.0L)
+#define floatx80_one (1.0L)
+#define floatx80_ln2 (0.69314718055994530943L)
+#define floatx80_pi (3.14159265358979323851L)
+#define floatx80_half (0.5L)
+
+/*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int floatx80_to_int32( floatx80 STATUS_PARAM );
commit c4b4c77a80cec85206e502578887d8c82b70d6af
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: add pi constants
    
    Add a pi constant for float32, float64, floatx80. It will be used by
    target-i386 and later by the trigonometric functions.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 90e0c41..7b3b88f 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -387,6 +387,7 @@ INLINE float32 float32_set_sign(float32 a, int sign)
 #define float32_zero make_float32(0)
 #define float32_one make_float32(0x3f800000)
 #define float32_ln2 make_float32(0x3f317218)
+#define float32_pi make_float32(0x40490fdb)
 #define float32_half make_float32(0x3f000000)
 #define float32_infinity make_float32(0x7f800000)
 
@@ -499,6 +500,7 @@ INLINE float64 float64_set_sign(float64 a, int sign)
 #define float64_zero make_float64(0)
 #define float64_one make_float64(0x3ff0000000000000LL)
 #define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
+#define float64_pi make_float64(0x400921fb54442d18LL)
 #define float64_half make_float64(0x3fe0000000000000LL)
 #define float64_infinity make_float64(0x7ff0000000000000LL)
 
@@ -588,6 +590,7 @@ INLINE int floatx80_is_any_nan(floatx80 a)
 #define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
 #define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
 #define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
+#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
 #define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
 #define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
 
commit f3218a8df0365e515f2100c92016217826811200
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: add floatx80 constants
    
    Add floatx80 constants similarly to float32 or float64.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 3363128..90e0c41 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -154,6 +154,7 @@ typedef struct {
     uint64_t low;
     uint16_t high;
 } floatx80;
+#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
 #endif
 #ifdef FLOAT128
 typedef struct {
@@ -584,6 +585,12 @@ INLINE int floatx80_is_any_nan(floatx80 a)
     return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
 }
 
+#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
+#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
+#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
+#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
+#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
+
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.  The
 | `high' and `low' values hold the most- and least-significant bits,
commit b76235e400be0e4f2c87ac4b678384f43a932181
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: fix floatx80_is_infinity()
    
    With floatx80, the explicit bit is set for infinity.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 340f0a9..3363128 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -566,7 +566,7 @@ INLINE floatx80 floatx80_chs(floatx80 a)
 
 INLINE int floatx80_is_infinity(floatx80 a)
 {
-    return (a.high & 0x7fff) == 0x7fff && a.low == 0;
+    return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
 }
 
 INLINE int floatx80_is_neg(floatx80 a)
commit e2f422047b6fd04c28630f80ab1161dbce07c6b7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Apr 20 13:04:22 2011 +0200

    softfloat: fix floatx80 handling of NaN
    
    The floatx80 format uses an explicit bit that should be taken into account
    when converting to and from commonNaN format.
    
    When converting to commonNaN, the explicit bit should be removed if it is
    a 1, and a default NaN should be used if it is 0.
    
    When converting from commonNan, the explicit bit should be added.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index b110187..9d68aae 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -603,9 +603,15 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
     commonNaNT z;
 
     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
-    z.sign = a.high>>15;
-    z.low = 0;
-    z.high = a.low;
+    if ( a.low >> 63 ) {
+        z.sign = a.high >> 15;
+        z.low = 0;
+        z.high = a.low << 1;
+    } else {
+        z.sign = floatx80_default_nan_high >> 15;
+        z.low = 0;
+        z.high = floatx80_default_nan_low << 1;
+    }
     return z;
 }
 
@@ -624,11 +630,14 @@ static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
         return z;
     }
 
-    if (a.high)
-        z.low = a.high;
-    else
+    if (a.high >> 1) {
+        z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
+        z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+    } else {
         z.low = floatx80_default_nan_low;
-    z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+        z.high = floatx80_default_nan_high;
+    }
+
     return z;
 }
 
commit da26fdc3145fc990762133beb8ad6bd67742a147
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 00:07:26 2010 +0100

    vmstate: port mac_dbdma
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index c108aee..ed4458e 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -810,30 +810,28 @@ static CPUReadMemoryFunc * const dbdma_read[] = {
     dbdma_readl,
 };
 
-static void dbdma_save(QEMUFile *f, void *opaque)
-{
-    DBDMAState *s = opaque;
-    unsigned int i, j;
-
-    for (i = 0; i < DBDMA_CHANNELS; i++)
-        for (j = 0; j < DBDMA_REGS; j++)
-            qemu_put_be32s(f, &s->channels[i].regs[j]);
-}
-
-static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
-{
-    DBDMAState *s = opaque;
-    unsigned int i, j;
-
-    if (version_id != 2)
-        return -EINVAL;
-
-    for (i = 0; i < DBDMA_CHANNELS; i++)
-        for (j = 0; j < DBDMA_REGS; j++)
-            qemu_get_be32s(f, &s->channels[i].regs[j]);
+static const VMStateDescription vmstate_dbdma_channel = {
+    .name = "dbdma_channel",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
+static const VMStateDescription vmstate_dbdma = {
+    .name = "dbdma",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields      = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
+                             vmstate_dbdma_channel, DBDMA_channel),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void dbdma_reset(void *opaque)
 {
@@ -852,7 +850,7 @@ void* DBDMA_init (int *dbdma_mem_index)
 
     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
                                               DEVICE_LITTLE_ENDIAN);
-    register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
+    vmstate_register(NULL, -1, &vmstate_dbdma, s);
     qemu_register_reset(dbdma_reset, s);
 
     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
commit c20df14b1336b409c48fbbbfeb448f0043df75d5
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 00:04:02 2010 +0100

    mac_dbdma: create DBDMAState instead of passing one array around
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 5680fa9..c108aee 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -165,6 +165,10 @@ typedef struct DBDMA_channel {
     int processing;
 } DBDMA_channel;
 
+typedef struct {
+    DBDMA_channel channels[DBDMA_CHANNELS];
+} DBDMAState;
+
 #ifdef DEBUG_DBDMA
 static void dump_dbdma_cmd(dbdma_cmd *cmd)
 {
@@ -617,31 +621,34 @@ static void channel_run(DBDMA_channel *ch)
     }
 }
 
-static void DBDMA_run (DBDMA_channel *ch)
+static void DBDMA_run(DBDMAState *s)
 {
     int channel;
 
-    for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) {
-            uint32_t status = ch->regs[DBDMA_STATUS];
-            if (!ch->processing && (status & RUN) && (status & ACTIVE))
-                channel_run(ch);
+    for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
+        DBDMA_channel *ch = &s->channels[channel];
+        uint32_t status = ch->regs[DBDMA_STATUS];
+        if (!ch->processing && (status & RUN) && (status & ACTIVE)) {
+            channel_run(ch);
+        }
     }
 }
 
 static void DBDMA_run_bh(void *opaque)
 {
-    DBDMA_channel *ch = opaque;
+    DBDMAState *s = opaque;
 
     DBDMA_DPRINTF("DBDMA_run_bh\n");
 
-    DBDMA_run(ch);
+    DBDMA_run(s);
 }
 
 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
                             DBDMA_rw rw, DBDMA_flush flush,
                             void *opaque)
 {
-    DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan;
+    DBDMAState *s = dbdma;
+    DBDMA_channel *ch = &s->channels[nchan];
 
     DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
 
@@ -700,7 +707,8 @@ static void dbdma_writel (void *opaque,
                           target_phys_addr_t addr, uint32_t value)
 {
     int channel = addr >> DBDMA_CHANNEL_SHIFT;
-    DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+    DBDMAState *s = opaque;
+    DBDMA_channel *ch = &s->channels[channel];
     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
 
     DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
@@ -749,7 +757,8 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
 {
     uint32_t value;
     int channel = addr >> DBDMA_CHANNEL_SHIFT;
-    DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+    DBDMAState *s = opaque;
+    DBDMA_channel *ch = &s->channels[channel];
     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
 
     value = ch->regs[reg];
@@ -803,17 +812,17 @@ static CPUReadMemoryFunc * const dbdma_read[] = {
 
 static void dbdma_save(QEMUFile *f, void *opaque)
 {
-    DBDMA_channel *s = opaque;
+    DBDMAState *s = opaque;
     unsigned int i, j;
 
     for (i = 0; i < DBDMA_CHANNELS; i++)
         for (j = 0; j < DBDMA_REGS; j++)
-            qemu_put_be32s(f, &s[i].regs[j]);
+            qemu_put_be32s(f, &s->channels[i].regs[j]);
 }
 
 static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
 {
-    DBDMA_channel *s = opaque;
+    DBDMAState *s = opaque;
     unsigned int i, j;
 
     if (version_id != 2)
@@ -821,25 +830,25 @@ static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
 
     for (i = 0; i < DBDMA_CHANNELS; i++)
         for (j = 0; j < DBDMA_REGS; j++)
-            qemu_get_be32s(f, &s[i].regs[j]);
+            qemu_get_be32s(f, &s->channels[i].regs[j]);
 
     return 0;
 }
 
 static void dbdma_reset(void *opaque)
 {
-    DBDMA_channel *s = opaque;
+    DBDMAState *s = opaque;
     int i;
 
     for (i = 0; i < DBDMA_CHANNELS; i++)
-        memset(s[i].regs, 0, DBDMA_SIZE);
+        memset(s->channels[i].regs, 0, DBDMA_SIZE);
 }
 
 void* DBDMA_init (int *dbdma_mem_index)
 {
-    DBDMA_channel *s;
+    DBDMAState *s;
 
-    s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
+    s = qemu_mallocz(sizeof(DBDMAState));
 
     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
                                               DEVICE_LITTLE_ENDIAN);
commit 9039d78e64648e6dca2aa7fe38c59ac2f5bac32b
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 16:59:33 2010 +0100

    vmstate: port piix4
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/piix4.c b/hw/piix4.c
index 40cd91a..71f1f84 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -72,19 +72,16 @@ static void piix4_reset(void *opaque)
     pci_conf[0xae] = 0x00;
 }
 
-static void piix_save(QEMUFile* f, void *opaque)
-{
-    PIIX4State *d = opaque;
-    pci_device_save(&d->dev, f);
-}
-
-static int piix_load(QEMUFile* f, void *opaque, int version_id)
-{
-    PIIX4State *d = opaque;
-    if (version_id != 2)
-        return -EINVAL;
-    return pci_device_load(&d->dev, f);
-}
+static const VMStateDescription vmstate_piix4 = {
+    .name = "PIIX4",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, PIIX4State),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int piix4_initfn(PCIDevice *dev)
 {
@@ -92,7 +89,6 @@ static int piix4_initfn(PCIDevice *dev)
     uint8_t *pci_conf;
 
     isa_bus_new(&d->dev.qdev);
-    register_savevm(&d->dev.qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
 
     pci_conf = d->dev.config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
@@ -117,6 +113,7 @@ static PCIDeviceInfo piix4_info[] = {
         .qdev.name    = "PIIX4",
         .qdev.desc    = "ISA bridge",
         .qdev.size    = sizeof(PIIX4State),
+        .qdev.vmsd    = &vmstate_piix4,
         .qdev.no_user = 1,
         .no_hotplug   = 1,
         .init         = piix4_initfn,
commit 1fc7cee0b40e23d3d8a7384df69c07e5dd5954ed
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 16:26:56 2010 +0100

    piix4: create PIIX4State
    
    It only contains a PCIDevice by know, but it makes easy to use migration code
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/piix4.c b/hw/piix4.c
index 72073cd..40cd91a 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -30,10 +30,14 @@
 
 PCIDevice *piix4_dev;
 
+typedef struct PIIX4State {
+    PCIDevice dev;
+} PIIX4State;
+
 static void piix4_reset(void *opaque)
 {
-    PCIDevice *d = opaque;
-    uint8_t *pci_conf = d->config;
+    PIIX4State *d = opaque;
+    uint8_t *pci_conf = d->dev.config;
 
     pci_conf[0x04] = 0x07; // master, memory and I/O
     pci_conf[0x05] = 0x00;
@@ -70,31 +74,32 @@ static void piix4_reset(void *opaque)
 
 static void piix_save(QEMUFile* f, void *opaque)
 {
-    PCIDevice *d = opaque;
-    pci_device_save(d, f);
+    PIIX4State *d = opaque;
+    pci_device_save(&d->dev, f);
 }
 
 static int piix_load(QEMUFile* f, void *opaque, int version_id)
 {
-    PCIDevice *d = opaque;
+    PIIX4State *d = opaque;
     if (version_id != 2)
         return -EINVAL;
-    return pci_device_load(d, f);
+    return pci_device_load(&d->dev, f);
 }
 
-static int piix4_initfn(PCIDevice *d)
+static int piix4_initfn(PCIDevice *dev)
 {
+    PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
     uint8_t *pci_conf;
 
-    isa_bus_new(&d->qdev);
-    register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
+    isa_bus_new(&d->dev.qdev);
+    register_savevm(&d->dev.qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
 
-    pci_conf = d->config;
+    pci_conf = d->dev.config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
 
-    piix4_dev = d;
+    piix4_dev = &d->dev;
     qemu_register_reset(piix4_reset, d);
     return 0;
 }
@@ -111,7 +116,7 @@ static PCIDeviceInfo piix4_info[] = {
     {
         .qdev.name    = "PIIX4",
         .qdev.desc    = "ISA bridge",
-        .qdev.size    = sizeof(PCIDevice),
+        .qdev.size    = sizeof(PIIX4State),
         .qdev.no_user = 1,
         .no_hotplug   = 1,
         .init         = piix4_initfn,
commit 8e470f8a77f6dfb0ca4bb087010b4bcd920a1d21
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:59:09 2010 +0100

    vmstate: port mac_nvram
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index 64f0192..61e53d2 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -105,24 +105,17 @@ static CPUReadMemoryFunc * const nvram_read[] = {
     &macio_nvram_readb,
 };
 
-static void macio_nvram_save(QEMUFile *f, void *opaque)
-{
-    MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
-    qemu_put_buffer(f, s->data, s->size);
-}
-
-static int macio_nvram_load(QEMUFile *f, void *opaque, int version_id)
-{
-    MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    qemu_get_buffer(f, s->data, s->size);
+static const VMStateDescription vmstate_macio_nvram = {
+    .name = "macio_nvram",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
 
 static void macio_nvram_reset(void *opaque)
 {
@@ -141,8 +134,7 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
     s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
                                           DEVICE_NATIVE_ENDIAN);
     *mem_index = s->mem_index;
-    register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
-                    macio_nvram_load, s);
+    vmstate_register(NULL, -1, &vmstate_macio_nvram, s);
     qemu_register_reset(macio_nvram_reset, s);
 
     return s;
commit 8a11f43bd5d42462c7d6a9321cefa59e78c69d51
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:54:21 2010 +0100

    mac_nvram: size is a size, no need to be a target dependent type
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index c2a2fc2..64f0192 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -38,7 +38,7 @@
 #endif
 
 struct MacIONVRAMState {
-    target_phys_addr_t size;
+    uint32_t size;
     int mem_index;
     unsigned int it_shift;
     uint8_t *data;
commit 7b9a3d86c1c5ed508ab07b536f44a308732b9069
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:50:10 2010 +0100

    vmstate: port nand
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/nand.c b/hw/nand.c
index 9f978d8..37e51d7 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -66,6 +66,8 @@ struct NANDFlashState {
     void (*blk_write)(NANDFlashState *s);
     void (*blk_erase)(NANDFlashState *s);
     void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+
+    uint32_t ioaddr_vmstate;
 };
 
 # define NAND_NO_AUTOINCR	0x00000001
@@ -281,48 +283,51 @@ static void nand_command(NANDFlashState *s)
     }
 }
 
-static void nand_save(QEMUFile *f, void *opaque)
+static void nand_pre_save(void *opaque)
 {
-    NANDFlashState *s = (NANDFlashState *) opaque;
-    qemu_put_byte(f, s->cle);
-    qemu_put_byte(f, s->ale);
-    qemu_put_byte(f, s->ce);
-    qemu_put_byte(f, s->wp);
-    qemu_put_byte(f, s->gnd);
-    qemu_put_buffer(f, s->io, sizeof(s->io));
-    qemu_put_be32(f, s->ioaddr - s->io);
-    qemu_put_be32(f, s->iolen);
-
-    qemu_put_be32s(f, &s->cmd);
-    qemu_put_be32s(f, &s->addr);
-    qemu_put_be32(f, s->addrlen);
-    qemu_put_be32(f, s->status);
-    qemu_put_be32(f, s->offset);
-    /* XXX: do we want to save s->storage too? */
+    NANDFlashState *s = opaque;
+
+    s->ioaddr_vmstate = s->ioaddr - s->io;
 }
 
-static int nand_load(QEMUFile *f, void *opaque, int version_id)
+static int nand_post_load(void *opaque, int version_id)
 {
-    NANDFlashState *s = (NANDFlashState *) opaque;
-    s->cle = qemu_get_byte(f);
-    s->ale = qemu_get_byte(f);
-    s->ce = qemu_get_byte(f);
-    s->wp = qemu_get_byte(f);
-    s->gnd = qemu_get_byte(f);
-    qemu_get_buffer(f, s->io, sizeof(s->io));
-    s->ioaddr = s->io + qemu_get_be32(f);
-    s->iolen = qemu_get_be32(f);
-    if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io)
+    NANDFlashState *s = opaque;
+
+    if (s->ioaddr_vmstate > sizeof(s->io)) {
         return -EINVAL;
+    }
+    s->ioaddr = s->io + s->ioaddr_vmstate;
 
-    qemu_get_be32s(f, &s->cmd);
-    qemu_get_be32s(f, &s->addr);
-    s->addrlen = qemu_get_be32(f);
-    s->status = qemu_get_be32(f);
-    s->offset = qemu_get_be32(f);
     return 0;
 }
 
+static const VMStateDescription vmstate_nand = {
+    .name = "nand",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save = nand_pre_save,
+    .post_load = nand_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(cle, NANDFlashState),
+        VMSTATE_UINT8(ale, NANDFlashState),
+        VMSTATE_UINT8(ce, NANDFlashState),
+        VMSTATE_UINT8(wp, NANDFlashState),
+        VMSTATE_UINT8(gnd, NANDFlashState),
+        VMSTATE_BUFFER(io, NANDFlashState),
+        VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
+        VMSTATE_INT32(iolen, NANDFlashState),
+        VMSTATE_UINT32(cmd, NANDFlashState),
+        VMSTATE_UINT32(addr, NANDFlashState),
+        VMSTATE_INT32(addrlen, NANDFlashState),
+        VMSTATE_INT32(status, NANDFlashState),
+        VMSTATE_INT32(offset, NANDFlashState),
+        /* XXX: do we want to save s->storage too? */
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 /*
  * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins.  Chip
  * outputs are R/B and eight I/O pins.
@@ -502,7 +507,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
        is used.  */
     s->ioaddr = s->io;
 
-    register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
+    vmstate_register(NULL, -1, &vmstate_nand, s);
 
     return s;
 }
commit 51db57f7e8ef46743cb3380bfd430d3ee1877866
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:39:22 2010 +0100

    nand: pin values are uint8_t
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/flash.h b/hw/flash.h
index d7d103e..c22e1a9 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -21,8 +21,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 typedef struct NANDFlashState NANDFlashState;
 NANDFlashState *nand_init(int manf_id, int chip_id);
 void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s,
-                int cle, int ale, int ce, int wp, int gnd);
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+                  uint8_t ce, uint8_t wp, uint8_t gnd);
 void nand_getpins(NANDFlashState *s, int *rb);
 void nand_setio(NANDFlashState *s, uint8_t value);
 uint8_t nand_getio(NANDFlashState *s);
diff --git a/hw/nand.c b/hw/nand.c
index f414aa1..9f978d8 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -52,7 +52,7 @@ struct NANDFlashState {
     BlockDriverState *bdrv;
     int mem_oob;
 
-    int cle, ale, ce, wp, gnd;
+    uint8_t cle, ale, ce, wp, gnd;
 
     uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
     uint8_t *ioaddr;
@@ -329,8 +329,8 @@ static int nand_load(QEMUFile *f, void *opaque, int version_id)
  *
  * CE, WP and R/B are active low.
  */
-void nand_setpins(NANDFlashState *s,
-                int cle, int ale, int ce, int wp, int gnd)
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+                  uint8_t ce, uint8_t wp, uint8_t gnd)
 {
     s->cle = cle;
     s->ale = ale;
commit 38cb3aa9b4d5b9085ff4635415b6d3c673e2dc7d
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:03:59 2010 +0100

    vmstate: port max111x
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/max111x.c b/hw/max111x.c
index 3adc3e4..70cd1af 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -94,36 +94,22 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
     return max111x_read(s);
 }
 
-static void max111x_save(QEMUFile *f, void *opaque)
-{
-    MAX111xState *s = (MAX111xState *) opaque;
-    int i;
-
-    qemu_put_8s(f, &s->tb1);
-    qemu_put_8s(f, &s->rb2);
-    qemu_put_8s(f, &s->rb3);
-    qemu_put_be32(f, s->inputs);
-    qemu_put_be32(f, s->com);
-    for (i = 0; i < s->inputs; i ++)
-        qemu_put_byte(f, s->input[i]);
-}
-
-static int max111x_load(QEMUFile *f, void *opaque, int version_id)
-{
-    MAX111xState *s = (MAX111xState *) opaque;
-    int i;
-
-    qemu_get_8s(f, &s->tb1);
-    qemu_get_8s(f, &s->rb2);
-    qemu_get_8s(f, &s->rb3);
-    if (s->inputs != qemu_get_be32(f))
-        return -EINVAL;
-    s->com = qemu_get_be32(f);
-    for (i = 0; i < s->inputs; i ++)
-        s->input[i] = qemu_get_byte(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_max111x = {
+    .name = "max111x",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(tb1, MAX111xState),
+        VMSTATE_UINT8(rb2, MAX111xState),
+        VMSTATE_UINT8(rb3, MAX111xState),
+        VMSTATE_INT32_EQUAL(inputs, MAX111xState),
+        VMSTATE_INT32(com, MAX111xState),
+        VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
+                                   vmstate_info_uint8, uint8_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int max111x_init(SSISlave *dev, int inputs)
 {
@@ -143,8 +129,7 @@ static int max111x_init(SSISlave *dev, int inputs)
     s->input[7] = 0x80;
     s->com = 0;
 
-    register_savevm(&dev->qdev, "max111x", -1, 0,
-                    max111x_save, max111x_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
     return 0;
 }
 
commit 54d970d134f3bf820f51266113f1b7489b794fe2
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:03:10 2010 +0100

    max111x: input field is only used as uint8_t
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/max111x.c b/hw/max111x.c
index 2844665..3adc3e4 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -15,7 +15,7 @@ typedef struct {
     uint8_t tb1, rb2, rb3;
     int cycle;
 
-    int input[8];
+    uint8_t input[8];
     int inputs, com;
 } MAX111xState;
 
commit 99838363ba37553321bc6a0274b08c4af65541ea
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 16:11:24 2010 +0100

    vmstate: port pxa2xx_lcd
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 55e95be..e524802 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -833,74 +833,26 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
     pxa2xx_lcdc_resize(s);
 }
 
-static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->irqlevel);
-    qemu_put_be32(f, s->transp);
-
-    for (i = 0; i < 6; i ++)
-        qemu_put_be32s(f, &s->control[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->status[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->ovl1c[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->ovl2c[i]);
-    qemu_put_be32s(f, &s->ccr);
-    qemu_put_be32s(f, &s->cmdcr);
-    qemu_put_be32s(f, &s->trgbr);
-    qemu_put_be32s(f, &s->tcr);
-    qemu_put_be32s(f, &s->liidr);
-    qemu_put_8s(f, &s->bscntr);
-
-    for (i = 0; i < 7; i ++) {
-        qemu_put_betl(f, s->dma_ch[i].branch);
-        qemu_put_byte(f, s->dma_ch[i].up);
-        qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
-        qemu_put_betl(f, s->dma_ch[i].descriptor);
-        qemu_put_betl(f, s->dma_ch[i].source);
-        qemu_put_be32s(f, &s->dma_ch[i].id);
-        qemu_put_be32s(f, &s->dma_ch[i].command);
+static const VMStateDescription vmstate_dma_channel = {
+    .name = "dma_channel",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINTTL(branch, struct DMAChannel),
+        VMSTATE_UINT8(up, struct DMAChannel),
+        VMSTATE_BUFFER(pbuffer, struct DMAChannel),
+        VMSTATE_UINTTL(descriptor, struct DMAChannel),
+        VMSTATE_UINTTL(source, struct DMAChannel),
+        VMSTATE_UINT32(id, struct DMAChannel),
+        VMSTATE_UINT32(command, struct DMAChannel),
+        VMSTATE_END_OF_LIST()
     }
-}
+};
 
-static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
+static int pxa2xx_lcdc_post_load(void *opaque, int version_id)
 {
-    PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
-    int i;
-
-    s->irqlevel = qemu_get_be32(f);
-    s->transp = qemu_get_be32(f);
-
-    for (i = 0; i < 6; i ++)
-        qemu_get_be32s(f, &s->control[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->status[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->ovl1c[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->ovl2c[i]);
-    qemu_get_be32s(f, &s->ccr);
-    qemu_get_be32s(f, &s->cmdcr);
-    qemu_get_be32s(f, &s->trgbr);
-    qemu_get_be32s(f, &s->tcr);
-    qemu_get_be32s(f, &s->liidr);
-    qemu_get_8s(f, &s->bscntr);
-
-    for (i = 0; i < 7; i ++) {
-        s->dma_ch[i].branch = qemu_get_betl(f);
-        s->dma_ch[i].up = qemu_get_byte(f);
-        qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
-        s->dma_ch[i].descriptor = qemu_get_betl(f);
-        s->dma_ch[i].source = qemu_get_betl(f);
-        qemu_get_be32s(f, &s->dma_ch[i].id);
-        qemu_get_be32s(f, &s->dma_ch[i].command);
-    }
+    PXA2xxLCDState *s = opaque;
 
     s->bpp = LCCR3_BPP(s->control[3]);
     s->xres = s->yres = s->pal_for = -1;
@@ -908,6 +860,31 @@ static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
+static const VMStateDescription vmstate_pxa2xx_lcdc = {
+    .name = "pxa2xx_lcdc",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = pxa2xx_lcdc_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(irqlevel, PXA2xxLCDState),
+        VMSTATE_INT32(transp, PXA2xxLCDState),
+        VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6),
+        VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2),
+        VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2),
+        VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2),
+        VMSTATE_UINT32(ccr, PXA2xxLCDState),
+        VMSTATE_UINT32(cmdcr, PXA2xxLCDState),
+        VMSTATE_UINT32(trgbr, PXA2xxLCDState),
+        VMSTATE_UINT32(tcr, PXA2xxLCDState),
+        VMSTATE_UINT32(liidr, PXA2xxLCDState),
+        VMSTATE_UINT8(bscntr, PXA2xxLCDState),
+        VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0,
+                             vmstate_dma_channel, struct DMAChannel),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 #define BITS 8
 #include "pxa2xx_template.h"
 #define BITS 15
@@ -972,8 +949,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
         exit(1);
     }
 
-    register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
-                    pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
 
     return s;
 }
commit 469954090ff1a11285a29c4e03df09c128ebc5bc
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 16:01:57 2010 +0100

    pxa2xx_lcd: up field is used as a bool and migrated as an uint8_t
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 9a19347..55e95be 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -17,7 +17,7 @@
 
 struct DMAChannel {
     target_phys_addr_t branch;
-    int up;
+    uint8_t up;
     uint8_t palette[1024];
     uint8_t pbuffer[1024];
     void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
commit 2b7251e0f2e9414f2440e9b485e95f337b869d53
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 15:56:04 2010 +0100

    pxa2xx_lcd: name anonymous struct
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 5b2b07e..9a19347 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -15,6 +15,20 @@
 #include "sysemu.h"
 #include "framebuffer.h"
 
+struct DMAChannel {
+    target_phys_addr_t branch;
+    int up;
+    uint8_t palette[1024];
+    uint8_t pbuffer[1024];
+    void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
+                   int *miny, int *maxy);
+
+    target_phys_addr_t descriptor;
+    target_phys_addr_t source;
+    uint32_t id;
+    uint32_t command;
+};
+
 struct PXA2xxLCDState {
     qemu_irq irq;
     int irqlevel;
@@ -50,19 +64,7 @@ struct PXA2xxLCDState {
     uint32_t liidr;
     uint8_t bscntr;
 
-    struct {
-        target_phys_addr_t branch;
-        int up;
-        uint8_t palette[1024];
-        uint8_t pbuffer[1024];
-        void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
-                        int *miny, int *maxy);
-
-        target_phys_addr_t descriptor;
-        target_phys_addr_t source;
-        uint32_t id;
-        uint32_t command;
-    } dma_ch[7];
+    struct DMAChannel dma_ch[7];
 
     qemu_irq vsync_cb;
     int orientation;
commit dd8a4dcda4c985cfa313cfe70ab0385c07341480
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:07:44 2010 +0100

    vmstate: stellaris use unused for placeholder entries
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 58aec19..ac9fcc1 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -290,8 +290,7 @@ static const VMStateDescription vmstate_stellaris_gptm = {
         VMSTATE_UINT32(control, gptm_state),
         VMSTATE_UINT32(state, gptm_state),
         VMSTATE_UINT32(mask, gptm_state),
-        VMSTATE_UINT32(mode[0], gptm_state),
-        VMSTATE_UINT32(mode[0], gptm_state),
+        VMSTATE_UNUSED(8),
         VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
         VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
         VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
commit 4483c7ac31f76e91fe69bf7f2346e77a10ac427e
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 02:36:38 2010 +0100

    vmstate: port stellaris gamepad
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 16aae96..06c5f9d 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -13,7 +13,7 @@
 typedef struct {
     qemu_irq irq;
     int keycode;
-    int pressed;
+    uint8_t pressed;
 } gamepad_button;
 
 typedef struct {
@@ -47,30 +47,29 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode)
     s->extension = 0;
 }
 
-static void stellaris_gamepad_save(QEMUFile *f, void *opaque)
-{
-    gamepad_state *s = (gamepad_state *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->extension);
-    for (i = 0; i < s->num_buttons; i++)
-        qemu_put_byte(f, s->buttons[i].pressed);
-}
-
-static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id)
-{
-    gamepad_state *s = (gamepad_state *)opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->extension = qemu_get_be32(f);
-    for (i = 0; i < s->num_buttons; i++)
-        s->buttons[i].pressed = qemu_get_byte(f);
+static const VMStateDescription vmstate_stellaris_button = {
+    .name = "stellaris_button",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(pressed, gamepad_button),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
+static const VMStateDescription vmstate_stellaris_gamepad = {
+    .name = "stellaris_gamepad",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(extension, gamepad_state),
+        VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0,
+                              vmstate_stellaris_button, gamepad_button),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 /* Returns an array 5 ouput slots.  */
 void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
@@ -86,6 +85,5 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
     }
     s->num_buttons = n;
     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
-    register_savevm(NULL, "stellaris_gamepad", -1, 1,
-                    stellaris_gamepad_save, stellaris_gamepad_load, s);
+    vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s);
 }
commit 0c067bbb26e3dae03807ba7eeb4bfd697f5f01c4
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 22:51:07 2010 +0100

    vmstate: port syborg_keyboard
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index d295e99..706a039 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -51,11 +51,11 @@ enum {
 
 typedef struct {
     SysBusDevice busdev;
-    int int_enabled;
+    uint32_t int_enabled;
     int extension_bit;
     uint32_t fifo_size;
     uint32_t *key_fifo;
-    int read_pos, read_count;
+    uint32_t read_pos, read_count;
     qemu_irq irq;
 } SyborgKeyboardState;
 
@@ -165,43 +165,21 @@ static void syborg_keyboard_event(void *opaque, int keycode)
     syborg_keyboard_update(s);
 }
 
-static void syborg_keyboard_save(QEMUFile *f, void *opaque)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->fifo_size);
-    qemu_put_be32(f, s->int_enabled);
-    qemu_put_be32(f, s->extension_bit);
-    qemu_put_be32(f, s->read_pos);
-    qemu_put_be32(f, s->read_count);
-    for (i = 0; i < s->fifo_size; i++) {
-        qemu_put_be32(f, s->key_fifo[i]);
-    }
-}
-
-static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
-    uint32_t val;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    val = qemu_get_be32(f);
-    if (val != s->fifo_size)
-        return -EINVAL;
-
-    s->int_enabled = qemu_get_be32(f);
-    s->extension_bit = qemu_get_be32(f);
-    s->read_pos = qemu_get_be32(f);
-    s->read_count = qemu_get_be32(f);
-    for (i = 0; i < s->fifo_size; i++) {
-        s->key_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_keyboard = {
+    .name = "syborg_keyboard",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
+        VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
+        VMSTATE_UINT32(read_pos, SyborgKeyboardState),
+        VMSTATE_UINT32(read_count, SyborgKeyboardState),
+        VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
+                              vmstate_info_uint32, uint32),
+        VMSTATE_END_OF_LIST()
     }
-    return 0;
-}
+};
 
 static int syborg_keyboard_init(SysBusDevice *dev)
 {
@@ -221,8 +199,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
 
     qemu_add_kbd_event_handler(syborg_keyboard_event, s);
 
-    register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
-                    syborg_keyboard_save, syborg_keyboard_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
     return 0;
 }
 
commit 8dc5907090fd35fd80e643534ab02092b73ec9cd
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 02:10:53 2010 +0100

    vmstate: port syborg_serial
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index 34ce076..df2950f 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -273,47 +273,24 @@ static CPUWriteMemoryFunc * const syborg_serial_writefn[] = {
      syborg_serial_write
 };
 
-static void syborg_serial_save(QEMUFile *f, void *opaque)
-{
-    SyborgSerialState *s = opaque;
-    int i;
-
-    qemu_put_be32(f, s->fifo_size);
-    qemu_put_be32(f, s->int_enable);
-    qemu_put_be32(f, s->read_pos);
-    qemu_put_be32(f, s->read_count);
-    qemu_put_be32(f, s->dma_tx_ptr);
-    qemu_put_be32(f, s->dma_rx_ptr);
-    qemu_put_be32(f, s->dma_rx_size);
-    for (i = 0; i < s->fifo_size; i++) {
-        qemu_put_be32(f, s->read_fifo[i]);
-    }
-}
-
-static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgSerialState *s = opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    i = qemu_get_be32(f);
-    if (s->fifo_size != i)
-        return -EINVAL;
-
-    s->int_enable = qemu_get_be32(f);
-    s->read_pos = qemu_get_be32(f);
-    s->read_count = qemu_get_be32(f);
-    s->dma_tx_ptr = qemu_get_be32(f);
-    s->dma_rx_ptr = qemu_get_be32(f);
-    s->dma_rx_size = qemu_get_be32(f);
-    for (i = 0; i < s->fifo_size; i++) {
-        s->read_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_serial = {
+    .name = "syborg_serial",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState),
+        VMSTATE_UINT32(int_enable, SyborgSerialState),
+        VMSTATE_INT32(read_pos, SyborgSerialState),
+        VMSTATE_INT32(read_count, SyborgSerialState),
+        VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState),
+        VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState),
+        VMSTATE_UINT32(dma_rx_size, SyborgSerialState),
+        VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1,
+                              vmstate_info_uint32, uint32),
+        VMSTATE_END_OF_LIST()
     }
-
-    return 0;
-}
+};
 
 static int syborg_serial_init(SysBusDevice *dev)
 {
@@ -336,8 +313,6 @@ static int syborg_serial_init(SysBusDevice *dev)
     }
     s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
 
-    register_savevm(&dev->qdev, "syborg_serial", -1, 1,
-                    syborg_serial_save, syborg_serial_load, s);
     return 0;
 }
 
@@ -345,6 +320,7 @@ static SysBusDeviceInfo syborg_serial_info = {
     .init = syborg_serial_init,
     .qdev.name  = "syborg,serial",
     .qdev.size  = sizeof(SyborgSerialState),
+    .qdev.vmsd  = &vmstate_syborg_serial,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16),
         DEFINE_PROP_END_OF_LIST(),
commit cf1d31dc5cd3a98199af6169d80a1a6d191d8e55
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 01:27:58 2010 +0100

    vmstate: port stellaris_adc
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 31aa102..58aec19 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1057,60 +1057,40 @@ static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
    stellaris_adc_write
 };
 
-static void stellaris_adc_save(QEMUFile *f, void *opaque)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-    int i;
-    int j;
-
-    qemu_put_be32(f, s->actss);
-    qemu_put_be32(f, s->ris);
-    qemu_put_be32(f, s->im);
-    qemu_put_be32(f, s->emux);
-    qemu_put_be32(f, s->ostat);
-    qemu_put_be32(f, s->ustat);
-    qemu_put_be32(f, s->sspri);
-    qemu_put_be32(f, s->sac);
-    for (i = 0; i < 4; i++) {
-        qemu_put_be32(f, s->fifo[i].state);
-        for (j = 0; j < 16; j++) {
-            qemu_put_be32(f, s->fifo[i].data[j]);
-        }
-        qemu_put_be32(f, s->ssmux[i]);
-        qemu_put_be32(f, s->ssctl[i]);
-    }
-    qemu_put_be32(f, s->noise);
-}
-
-static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-    int i;
-    int j;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->actss = qemu_get_be32(f);
-    s->ris = qemu_get_be32(f);
-    s->im = qemu_get_be32(f);
-    s->emux = qemu_get_be32(f);
-    s->ostat = qemu_get_be32(f);
-    s->ustat = qemu_get_be32(f);
-    s->sspri = qemu_get_be32(f);
-    s->sac = qemu_get_be32(f);
-    for (i = 0; i < 4; i++) {
-        s->fifo[i].state = qemu_get_be32(f);
-        for (j = 0; j < 16; j++) {
-            s->fifo[i].data[j] = qemu_get_be32(f);
-        }
-        s->ssmux[i] = qemu_get_be32(f);
-        s->ssctl[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_stellaris_adc = {
+    .name = "stellaris_adc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(actss, stellaris_adc_state),
+        VMSTATE_UINT32(ris, stellaris_adc_state),
+        VMSTATE_UINT32(im, stellaris_adc_state),
+        VMSTATE_UINT32(emux, stellaris_adc_state),
+        VMSTATE_UINT32(ostat, stellaris_adc_state),
+        VMSTATE_UINT32(ustat, stellaris_adc_state),
+        VMSTATE_UINT32(sspri, stellaris_adc_state),
+        VMSTATE_UINT32(sac, stellaris_adc_state),
+        VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
+        VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
+        VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
+        VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
+        VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
+        VMSTATE_UINT32(noise, stellaris_adc_state),
+        VMSTATE_END_OF_LIST()
     }
-    s->noise = qemu_get_be32(f);
-
-    return 0;
-}
+};
 
 static int stellaris_adc_init(SysBusDevice *dev)
 {
@@ -1128,8 +1108,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
-                    stellaris_adc_save, stellaris_adc_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
     return 0;
 }
 
commit 80a526802c39e95ea0e65b879c91f240185889f2
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Dec 3 00:37:35 2010 +0100

    vmstate: port syborg_pointer
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index a886888..2f99707 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -152,52 +152,36 @@ static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
     syborg_pointer_update(s);
 }
 
-static void syborg_pointer_save(QEMUFile *f, void *opaque)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->fifo_size);
-    qemu_put_be32(f, s->absolute);
-    qemu_put_be32(f, s->int_enabled);
-    qemu_put_be32(f, s->read_pos);
-    qemu_put_be32(f, s->read_count);
-    for (i = 0; i < s->fifo_size; i++) {
-        qemu_put_be32(f, s->event_fifo[i].x);
-        qemu_put_be32(f, s->event_fifo[i].y);
-        qemu_put_be32(f, s->event_fifo[i].z);
-        qemu_put_be32(f, s->event_fifo[i].pointer_buttons);
+static const VMStateDescription vmstate_event_data = {
+    .name = "dbma_channel",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(x, event_data),
+        VMSTATE_INT32(y, event_data),
+        VMSTATE_INT32(z, event_data),
+        VMSTATE_INT32(pointer_buttons, event_data),
+        VMSTATE_END_OF_LIST()
     }
-}
+};
 
-static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgPointerState *s = (SyborgPointerState *)opaque;
-    uint32_t val;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    val = qemu_get_be32(f);
-    if (val != s->fifo_size)
-        return -EINVAL;
-
-    val = qemu_get_be32(f);
-    if (val != s->absolute)
-        return -EINVAL;
-
-    s->int_enabled = qemu_get_be32(f);
-    s->read_pos = qemu_get_be32(f);
-    s->read_count = qemu_get_be32(f);
-    for (i = 0; i < s->fifo_size; i++) {
-        s->event_fifo[i].x = qemu_get_be32(f);
-        s->event_fifo[i].y = qemu_get_be32(f);
-        s->event_fifo[i].z = qemu_get_be32(f);
-        s->event_fifo[i].pointer_buttons = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_pointer = {
+    .name = "syborg_pointer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState),
+        VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState),
+        VMSTATE_INT32(int_enabled, SyborgPointerState),
+        VMSTATE_INT32(read_pos, SyborgPointerState),
+        VMSTATE_INT32(read_count, SyborgPointerState),
+        VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size,
+                                     1, vmstate_event_data, event_data),
+        VMSTATE_END_OF_LIST()
     }
-    return 0;
-}
+};
 
 static int syborg_pointer_init(SysBusDevice *dev)
 {
@@ -219,8 +203,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
     qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
                                  "Syborg Pointer");
 
-    register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
-                    syborg_pointer_save, syborg_pointer_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s);
     return 0;
 }
 
commit b605f22212875d95e9c5f82369d48fe5cd8d10e4
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 17:27:49 2010 +0100

    vmstate: port ppc4xx_pci
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index f62f1f9..299473c 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -285,50 +285,48 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pci_irqs[irq_num], level);
 }
 
-static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
-{
-    PPC4xxPCIState *controller = opaque;
-    int i;
-
-    pci_device_save(controller->pci_dev, f);
-
-    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
-        qemu_put_be32s(f, &controller->pmm[i].la);
-        qemu_put_be32s(f, &controller->pmm[i].ma);
-        qemu_put_be32s(f, &controller->pmm[i].pcila);
-        qemu_put_be32s(f, &controller->pmm[i].pciha);
-    }
-
-    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
-        qemu_put_be32s(f, &controller->ptm[i].ms);
-        qemu_put_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_pci_master_map = {
+    .name = "pci_master_map",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(la, struct PCIMasterMap),
+        VMSTATE_UINT32(ma, struct PCIMasterMap),
+        VMSTATE_UINT32(pcila, struct PCIMasterMap),
+        VMSTATE_UINT32(pciha, struct PCIMasterMap),
+        VMSTATE_END_OF_LIST()
     }
-}
-
-static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PPC4xxPCIState *controller = opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    pci_device_load(controller->pci_dev, f);
+};
 
-    for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
-        qemu_get_be32s(f, &controller->pmm[i].la);
-        qemu_get_be32s(f, &controller->pmm[i].ma);
-        qemu_get_be32s(f, &controller->pmm[i].pcila);
-        qemu_get_be32s(f, &controller->pmm[i].pciha);
+static const VMStateDescription vmstate_pci_target_map = {
+    .name = "pci_target_map",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(ms, struct PCITargetMap),
+        VMSTATE_UINT32(la, struct PCITargetMap),
+        VMSTATE_END_OF_LIST()
     }
+};
 
-    for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
-        qemu_get_be32s(f, &controller->ptm[i].ms);
-        qemu_get_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_ppc4xx_pci = {
+    .name = "ppc4xx_pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
+        VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
+                             vmstate_pci_master_map,
+                             struct PCIMasterMap),
+        VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
+                             vmstate_pci_target_map,
+                             struct PCITargetMap),
+        VMSTATE_END_OF_LIST()
     }
-
-    return 0;
-}
+};
 
 /* XXX Interrupt acknowledge cycles not supported. */
 PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
@@ -381,8 +379,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     qemu_register_reset(ppc4xx_pci_reset, controller);
 
     /* XXX load/save code not tested. */
-    register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
-                    1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
+    vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
+                     &vmstate_ppc4xx_pci, controller);
 
     return controller->pci_state.bus;
 
commit e0433ecc6ead41f1581113eb892f744235f12120
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 15:29:42 2010 +0100

    vmstate: port ppce500_pci
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 2fc8792..83a20e4 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -216,56 +216,49 @@ static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[irq_num], level);
 }
 
-static void ppce500_pci_save(QEMUFile *f, void *opaque)
-{
-    PPCE500PCIState *controller = opaque;
-    int i;
-
-    pci_device_save(controller->pci_dev, f);
-
-    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
-        qemu_put_be32s(f, &controller->pob[i].potar);
-        qemu_put_be32s(f, &controller->pob[i].potear);
-        qemu_put_be32s(f, &controller->pob[i].powbar);
-        qemu_put_be32s(f, &controller->pob[i].powar);
-    }
-
-    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
-        qemu_put_be32s(f, &controller->pib[i].pitar);
-        qemu_put_be32s(f, &controller->pib[i].piwbar);
-        qemu_put_be32s(f, &controller->pib[i].piwbear);
-        qemu_put_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_pci_outbound = {
+    .name = "pci_outbound",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(potar, struct pci_outbound),
+        VMSTATE_UINT32(potear, struct pci_outbound),
+        VMSTATE_UINT32(powbar, struct pci_outbound),
+        VMSTATE_UINT32(powar, struct pci_outbound),
+        VMSTATE_END_OF_LIST()
     }
-    qemu_put_be32s(f, &controller->gasket_time);
-}
-
-static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PPCE500PCIState *controller = opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    pci_device_load(controller->pci_dev, f);
+};
 
-    for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
-        qemu_get_be32s(f, &controller->pob[i].potar);
-        qemu_get_be32s(f, &controller->pob[i].potear);
-        qemu_get_be32s(f, &controller->pob[i].powbar);
-        qemu_get_be32s(f, &controller->pob[i].powar);
+static const VMStateDescription vmstate_pci_inbound = {
+    .name = "pci_inbound",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(pitar, struct pci_inbound),
+        VMSTATE_UINT32(piwbar, struct pci_inbound),
+        VMSTATE_UINT32(piwbear, struct pci_inbound),
+        VMSTATE_UINT32(piwar, struct pci_inbound),
+        VMSTATE_END_OF_LIST()
     }
+};
 
-    for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
-        qemu_get_be32s(f, &controller->pib[i].pitar);
-        qemu_get_be32s(f, &controller->pib[i].piwbar);
-        qemu_get_be32s(f, &controller->pib[i].piwbear);
-        qemu_get_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_ppce500_pci = {
+    .name = "ppce500_pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
+        VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
+                             vmstate_pci_outbound, struct pci_outbound),
+        VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
+                             vmstate_pci_outbound, struct pci_inbound),
+        VMSTATE_UINT32(gasket_time, PPCE500PCIState),
+        VMSTATE_END_OF_LIST()
     }
-    qemu_get_be32s(f, &controller->gasket_time);
-
-    return 0;
-}
+};
 
 PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
 {
@@ -314,8 +307,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
                                    PCIE500_REG_SIZE, index);
 
     /* XXX load/save code not tested. */
-    register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
-                    1, ppce500_pci_save, ppce500_pci_load, controller);
+    vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
+                     controller);
 
     return controller->pci_state.bus;
 
commit f0ab24ce69347f71a5952b105777bfe22665259a
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:54:38 2010 +0100

    vmstate: port pxa2xx_pm
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index e174c20..ac5d95d 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -146,25 +146,16 @@ static CPUWriteMemoryFunc * const pxa2xx_pm_writefn[] = {
     pxa2xx_pm_write,
 };
 
-static void pxa2xx_pm_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 0x40; i ++)
-        qemu_put_be32s(f, &s->pm_regs[i]);
-}
-
-static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 0x40; i ++)
-        qemu_get_be32s(f, &s->pm_regs[i]);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_pm = {
+    .name = "pxa2xx_pm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 #define CCCR	0x00	/* Core Clock Configuration register */
 #define CKEN	0x04	/* Clock Enable register */
@@ -2168,7 +2159,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2304,7 +2295,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
-    register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
     s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
commit d102d49545273661016f66646a9f56ee52b2aee5
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:36:57 2010 +0100

    vmstate: port pxa2xx_mm
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index a824c22..e174c20 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -516,25 +516,16 @@ static CPUWriteMemoryFunc * const pxa2xx_mm_writefn[] = {
     pxa2xx_mm_write,
 };
 
-static void pxa2xx_mm_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 0x1a; i ++)
-        qemu_put_be32s(f, &s->mm_regs[i]);
-}
-
-static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 0x1a; i ++)
-        qemu_get_be32s(f, &s->mm_regs[i]);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_mm = {
+    .name = "pxa2xx_mm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 /* Synchronous Serial Ports */
 typedef struct {
@@ -2171,7 +2162,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
@@ -2307,7 +2298,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
-    register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
commit ae1f90de0664475cd1f12c5b229f0cb99bd8fcc3
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:31:14 2010 +0100

    vmstate: port pxa2xx_cm
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 96932ef..a824c22 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -227,29 +227,18 @@ static CPUWriteMemoryFunc * const pxa2xx_cm_writefn[] = {
     pxa2xx_cm_write,
 };
 
-static void pxa2xx_cm_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 4; i ++)
-        qemu_put_be32s(f, &s->cm_regs[i]);
-    qemu_put_be32s(f, &s->clkcfg);
-    qemu_put_be32s(f, &s->pmnc);
-}
-
-static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-    int i;
-
-    for (i = 0; i < 4; i ++)
-        qemu_get_be32s(f, &s->cm_regs[i]);
-    qemu_get_be32s(f, &s->clkcfg);
-    qemu_get_be32s(f, &s->pmnc);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_cm = {
+    .name = "pxa2xx_cm",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
+        VMSTATE_UINT32(clkcfg, PXA2xxState),
+        VMSTATE_UINT32(pmnc, PXA2xxState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
 {
@@ -2171,7 +2160,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -2307,7 +2296,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
-    register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
commit 9f5dfe298bbbf539b7a4ee802f274adff52b8648
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:14:56 2010 +0100

    vmstate: port pxa2xx_i2s
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9b95e2c..96932ef 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1748,39 +1748,23 @@ static CPUWriteMemoryFunc * const pxa2xx_i2s_writefn[] = {
     pxa2xx_i2s_write,
 };
 
-static void pxa2xx_i2s_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
-    qemu_put_be32s(f, &s->control[0]);
-    qemu_put_be32s(f, &s->control[1]);
-    qemu_put_be32s(f, &s->status);
-    qemu_put_be32s(f, &s->mask);
-    qemu_put_be32s(f, &s->clk);
-
-    qemu_put_be32(f, s->enable);
-    qemu_put_be32(f, s->rx_len);
-    qemu_put_be32(f, s->tx_len);
-    qemu_put_be32(f, s->fifo_len);
-}
-
-static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
-    qemu_get_be32s(f, &s->control[0]);
-    qemu_get_be32s(f, &s->control[1]);
-    qemu_get_be32s(f, &s->status);
-    qemu_get_be32s(f, &s->mask);
-    qemu_get_be32s(f, &s->clk);
-
-    s->enable = qemu_get_be32(f);
-    s->rx_len = qemu_get_be32(f);
-    s->tx_len = qemu_get_be32(f);
-    s->fifo_len = qemu_get_be32(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_i2s = {
+    .name = "pxa2xx_i2s",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
+        VMSTATE_UINT32(status, PXA2xxI2SState),
+        VMSTATE_UINT32(mask, PXA2xxI2SState),
+        VMSTATE_UINT32(clk, PXA2xxI2SState),
+        VMSTATE_INT32(enable, PXA2xxI2SState),
+        VMSTATE_INT32(rx_len, PXA2xxI2SState),
+        VMSTATE_INT32(tx_len, PXA2xxI2SState),
+        VMSTATE_INT32(fifo_len, PXA2xxI2SState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
 {
@@ -1822,8 +1806,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
                     pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100000, iomemtype);
 
-    register_savevm(NULL, "pxa2xx_i2s", base, 0,
-                    pxa2xx_i2s_save, pxa2xx_i2s_load, s);
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
 
     return s;
 }
commit 10f85a2934eb0b59470015b1243acc9369f71fd0
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 14:07:01 2010 +0100

    vmstate: port stellaris gptm
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 11d618d..31aa102 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -279,64 +279,29 @@ static CPUWriteMemoryFunc * const gptm_writefn[] = {
    gptm_write
 };
 
-static void gptm_save(QEMUFile *f, void *opaque)
-{
-    gptm_state *s = (gptm_state *)opaque;
-
-    qemu_put_be32(f, s->config);
-    qemu_put_be32(f, s->mode[0]);
-    qemu_put_be32(f, s->mode[1]);
-    qemu_put_be32(f, s->control);
-    qemu_put_be32(f, s->state);
-    qemu_put_be32(f, s->mask);
-    qemu_put_be32(f, s->mode[0]);
-    qemu_put_be32(f, s->mode[0]);
-    qemu_put_be32(f, s->load[0]);
-    qemu_put_be32(f, s->load[1]);
-    qemu_put_be32(f, s->match[0]);
-    qemu_put_be32(f, s->match[1]);
-    qemu_put_be32(f, s->prescale[0]);
-    qemu_put_be32(f, s->prescale[1]);
-    qemu_put_be32(f, s->match_prescale[0]);
-    qemu_put_be32(f, s->match_prescale[1]);
-    qemu_put_be32(f, s->rtc);
-    qemu_put_be64(f, s->tick[0]);
-    qemu_put_be64(f, s->tick[1]);
-    qemu_put_timer(f, s->timer[0]);
-    qemu_put_timer(f, s->timer[1]);
-}
-
-static int gptm_load(QEMUFile *f, void *opaque, int version_id)
-{
-    gptm_state *s = (gptm_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->config = qemu_get_be32(f);
-    s->mode[0] = qemu_get_be32(f);
-    s->mode[1] = qemu_get_be32(f);
-    s->control = qemu_get_be32(f);
-    s->state = qemu_get_be32(f);
-    s->mask = qemu_get_be32(f);
-    s->mode[0] = qemu_get_be32(f);
-    s->mode[0] = qemu_get_be32(f);
-    s->load[0] = qemu_get_be32(f);
-    s->load[1] = qemu_get_be32(f);
-    s->match[0] = qemu_get_be32(f);
-    s->match[1] = qemu_get_be32(f);
-    s->prescale[0] = qemu_get_be32(f);
-    s->prescale[1] = qemu_get_be32(f);
-    s->match_prescale[0] = qemu_get_be32(f);
-    s->match_prescale[1] = qemu_get_be32(f);
-    s->rtc = qemu_get_be32(f);
-    s->tick[0] = qemu_get_be64(f);
-    s->tick[1] = qemu_get_be64(f);
-    qemu_get_timer(f, s->timer[0]);
-    qemu_get_timer(f, s->timer[1]);
-
-    return 0;
-}
+static const VMStateDescription vmstate_stellaris_gptm = {
+    .name = "stellaris_gptm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(config, gptm_state),
+        VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
+        VMSTATE_UINT32(control, gptm_state),
+        VMSTATE_UINT32(state, gptm_state),
+        VMSTATE_UINT32(mask, gptm_state),
+        VMSTATE_UINT32(mode[0], gptm_state),
+        VMSTATE_UINT32(mode[0], gptm_state),
+        VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
+        VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
+        VMSTATE_UINT32(rtc, gptm_state),
+        VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
+        VMSTATE_TIMER_ARRAY(timer, gptm_state, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int stellaris_gptm_init(SysBusDevice *dev)
 {
@@ -354,8 +319,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     s->opaque[0] = s->opaque[1] = s;
     s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
     s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
-    register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
-                    gptm_save, gptm_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
     return 0;
 }
 
commit c0a93a9efabae3c9a8500bf2f14ffb06e313dc73
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 13:53:24 2010 +0100

    vmstate: port cuda
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/cuda.c b/hw/cuda.c
index 37aa3f4..065c362 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -644,80 +644,56 @@ static CPUReadMemoryFunc * const cuda_read[] = {
     &cuda_readl,
 };
 
-static void cuda_save_timer(QEMUFile *f, CUDATimer *s)
+static bool cuda_timer_exist(void *opaque, int version_id)
 {
-    qemu_put_be16s(f, &s->latch);
-    qemu_put_be16s(f, &s->counter_value);
-    qemu_put_sbe64s(f, &s->load_time);
-    qemu_put_sbe64s(f, &s->next_irq_time);
-    if (s->timer)
-        qemu_put_timer(f, s->timer);
-}
-
-static void cuda_save(QEMUFile *f, void *opaque)
-{
-    CUDAState *s = (CUDAState *)opaque;
-
-    qemu_put_ubyte(f, s->b);
-    qemu_put_ubyte(f, s->a);
-    qemu_put_ubyte(f, s->dirb);
-    qemu_put_ubyte(f, s->dira);
-    qemu_put_ubyte(f, s->sr);
-    qemu_put_ubyte(f, s->acr);
-    qemu_put_ubyte(f, s->pcr);
-    qemu_put_ubyte(f, s->ifr);
-    qemu_put_ubyte(f, s->ier);
-    qemu_put_ubyte(f, s->anh);
-    qemu_put_sbe32s(f, &s->data_in_size);
-    qemu_put_sbe32s(f, &s->data_in_index);
-    qemu_put_sbe32s(f, &s->data_out_index);
-    qemu_put_ubyte(f, s->autopoll);
-    qemu_put_buffer(f, s->data_in, sizeof(s->data_in));
-    qemu_put_buffer(f, s->data_out, sizeof(s->data_out));
-    qemu_put_be32s(f, &s->tick_offset);
-    cuda_save_timer(f, &s->timers[0]);
-    cuda_save_timer(f, &s->timers[1]);
-}
+    CUDATimer *s = opaque;
 
-static void cuda_load_timer(QEMUFile *f, CUDATimer *s)
-{
-    qemu_get_be16s(f, &s->latch);
-    qemu_get_be16s(f, &s->counter_value);
-    qemu_get_sbe64s(f, &s->load_time);
-    qemu_get_sbe64s(f, &s->next_irq_time);
-    if (s->timer)
-        qemu_get_timer(f, s->timer);
+    return s->timer != NULL;
 }
 
-static int cuda_load(QEMUFile *f, void *opaque, int version_id)
-{
-    CUDAState *s = (CUDAState *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->b = qemu_get_ubyte(f);
-    s->a = qemu_get_ubyte(f);
-    s->dirb = qemu_get_ubyte(f);
-    s->dira = qemu_get_ubyte(f);
-    s->sr = qemu_get_ubyte(f);
-    s->acr = qemu_get_ubyte(f);
-    s->pcr = qemu_get_ubyte(f);
-    s->ifr = qemu_get_ubyte(f);
-    s->ier = qemu_get_ubyte(f);
-    s->anh = qemu_get_ubyte(f);
-    qemu_get_sbe32s(f, &s->data_in_size);
-    qemu_get_sbe32s(f, &s->data_in_index);
-    qemu_get_sbe32s(f, &s->data_out_index);
-    s->autopoll = qemu_get_ubyte(f);
-    qemu_get_buffer(f, s->data_in, sizeof(s->data_in));
-    qemu_get_buffer(f, s->data_out, sizeof(s->data_out));
-    qemu_get_be32s(f, &s->tick_offset);
-    cuda_load_timer(f, &s->timers[0]);
-    cuda_load_timer(f, &s->timers[1]);
+static const VMStateDescription vmstate_cuda_timer = {
+    .name = "cuda_timer",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT16(latch, CUDATimer),
+        VMSTATE_UINT16(counter_value, CUDATimer),
+        VMSTATE_INT64(load_time, CUDATimer),
+        VMSTATE_INT64(next_irq_time, CUDATimer),
+        VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
+static const VMStateDescription vmstate_cuda = {
+    .name = "cuda",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(a, CUDAState),
+        VMSTATE_UINT8(b, CUDAState),
+        VMSTATE_UINT8(dira, CUDAState),
+        VMSTATE_UINT8(dirb, CUDAState),
+        VMSTATE_UINT8(sr, CUDAState),
+        VMSTATE_UINT8(acr, CUDAState),
+        VMSTATE_UINT8(pcr, CUDAState),
+        VMSTATE_UINT8(ifr, CUDAState),
+        VMSTATE_UINT8(ier, CUDAState),
+        VMSTATE_UINT8(anh, CUDAState),
+        VMSTATE_INT32(data_in_size, CUDAState),
+        VMSTATE_INT32(data_in_index, CUDAState),
+        VMSTATE_INT32(data_out_index, CUDAState),
+        VMSTATE_UINT8(autopoll, CUDAState),
+        VMSTATE_BUFFER(data_in, CUDAState),
+        VMSTATE_BUFFER(data_out, CUDAState),
+        VMSTATE_UINT32(tick_offset, CUDAState),
+        VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
+                             vmstate_cuda_timer, CUDATimer),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void cuda_reset(void *opaque)
 {
@@ -764,6 +740,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
     s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
     *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
                                              DEVICE_NATIVE_ENDIAN);
-    register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
+    vmstate_register(NULL, -1, &vmstate_cuda, s);
     qemu_register_reset(cuda_reset, s);
 }
commit 4acd38cef07820238e9d76ae68f14689f9764ef0
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 13:17:23 2010 +0100

    vmstate: port heathrow_pic
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index b19b754..5fd71a0 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -159,42 +159,31 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level)
     heathrow_pic_update(s);
 }
 
-static void heathrow_pic_save_one(QEMUFile *f, HeathrowPIC *s)
-{
-    qemu_put_be32s(f, &s->events);
-    qemu_put_be32s(f, &s->mask);
-    qemu_put_be32s(f, &s->levels);
-    qemu_put_be32s(f, &s->level_triggered);
-}
-
-static void heathrow_pic_save(QEMUFile *f, void *opaque)
-{
-    HeathrowPICS *s = (HeathrowPICS *)opaque;
-
-    heathrow_pic_save_one(f, &s->pics[0]);
-    heathrow_pic_save_one(f, &s->pics[1]);
-}
-
-static void heathrow_pic_load_one(QEMUFile *f, HeathrowPIC *s)
-{
-    qemu_get_be32s(f, &s->events);
-    qemu_get_be32s(f, &s->mask);
-    qemu_get_be32s(f, &s->levels);
-    qemu_get_be32s(f, &s->level_triggered);
-}
-
-static int heathrow_pic_load(QEMUFile *f, void *opaque, int version_id)
-{
-    HeathrowPICS *s = (HeathrowPICS *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    heathrow_pic_load_one(f, &s->pics[0]);
-    heathrow_pic_load_one(f, &s->pics[1]);
+static const VMStateDescription vmstate_heathrow_pic_one = {
+    .name = "heathrow_pic_one",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(events, HeathrowPIC),
+        VMSTATE_UINT32(mask, HeathrowPIC),
+        VMSTATE_UINT32(levels, HeathrowPIC),
+        VMSTATE_UINT32(level_triggered, HeathrowPIC),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
-    return 0;
-}
+static const VMStateDescription vmstate_heathrow_pic = {
+    .name = "heathrow_pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1,
+                             vmstate_heathrow_pic_one, HeathrowPIC),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void heathrow_pic_reset_one(HeathrowPIC *s)
 {
@@ -223,8 +212,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     *pmem_index = cpu_register_io_memory(pic_read, pic_write, s,
                                          DEVICE_LITTLE_ENDIAN);
 
-    register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
-                    heathrow_pic_load, s);
+    vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
     qemu_register_reset(heathrow_pic_reset, s);
     return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
 }
commit 075790c2c24f0dee15c584ae5c49903a52343bd4
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 12:43:50 2010 +0100

    vmstate: port pl022 ssp
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pl022.c b/hw/pl022.c
index ffe05ab..00e494a 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -239,54 +239,42 @@ static CPUWriteMemoryFunc * const pl022_writefn[] = {
    pl022_write
 };
 
-static void pl022_save(QEMUFile *f, void *opaque)
-{
-    pl022_state *s = (pl022_state *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->cr0);
-    qemu_put_be32(f, s->cr1);
-    qemu_put_be32(f, s->bitmask);
-    qemu_put_be32(f, s->sr);
-    qemu_put_be32(f, s->cpsr);
-    qemu_put_be32(f, s->is);
-    qemu_put_be32(f, s->im);
-    qemu_put_be32(f, s->tx_fifo_head);
-    qemu_put_be32(f, s->rx_fifo_head);
-    qemu_put_be32(f, s->tx_fifo_len);
-    qemu_put_be32(f, s->rx_fifo_len);
-    for (i = 0; i < 8; i++) {
-        qemu_put_be16(f, s->tx_fifo[i]);
-        qemu_put_be16(f, s->rx_fifo[i]);
-    }
-}
-
-static int pl022_load(QEMUFile *f, void *opaque, int version_id)
-{
-    pl022_state *s = (pl022_state *)opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->cr0 = qemu_get_be32(f);
-    s->cr1 = qemu_get_be32(f);
-    s->bitmask = qemu_get_be32(f);
-    s->sr = qemu_get_be32(f);
-    s->cpsr = qemu_get_be32(f);
-    s->is = qemu_get_be32(f);
-    s->im = qemu_get_be32(f);
-    s->tx_fifo_head = qemu_get_be32(f);
-    s->rx_fifo_head = qemu_get_be32(f);
-    s->tx_fifo_len = qemu_get_be32(f);
-    s->rx_fifo_len = qemu_get_be32(f);
-    for (i = 0; i < 8; i++) {
-        s->tx_fifo[i] = qemu_get_be16(f);
-        s->rx_fifo[i] = qemu_get_be16(f);
+static const VMStateDescription vmstate_pl022 = {
+    .name = "pl022_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(cr0, pl022_state),
+        VMSTATE_UINT32(cr1, pl022_state),
+        VMSTATE_UINT32(bitmask, pl022_state),
+        VMSTATE_UINT32(sr, pl022_state),
+        VMSTATE_UINT32(cpsr, pl022_state),
+        VMSTATE_UINT32(is, pl022_state),
+        VMSTATE_UINT32(im, pl022_state),
+        VMSTATE_INT32(tx_fifo_head, pl022_state),
+        VMSTATE_INT32(rx_fifo_head, pl022_state),
+        VMSTATE_INT32(tx_fifo_len, pl022_state),
+        VMSTATE_INT32(rx_fifo_len, pl022_state),
+        VMSTATE_UINT16(tx_fifo[0], pl022_state),
+        VMSTATE_UINT16(rx_fifo[0], pl022_state),
+        VMSTATE_UINT16(tx_fifo[1], pl022_state),
+        VMSTATE_UINT16(rx_fifo[1], pl022_state),
+        VMSTATE_UINT16(tx_fifo[2], pl022_state),
+        VMSTATE_UINT16(rx_fifo[2], pl022_state),
+        VMSTATE_UINT16(tx_fifo[3], pl022_state),
+        VMSTATE_UINT16(rx_fifo[3], pl022_state),
+        VMSTATE_UINT16(tx_fifo[4], pl022_state),
+        VMSTATE_UINT16(rx_fifo[4], pl022_state),
+        VMSTATE_UINT16(tx_fifo[5], pl022_state),
+        VMSTATE_UINT16(rx_fifo[5], pl022_state),
+        VMSTATE_UINT16(tx_fifo[6], pl022_state),
+        VMSTATE_UINT16(rx_fifo[6], pl022_state),
+        VMSTATE_UINT16(tx_fifo[7], pl022_state),
+        VMSTATE_UINT16(rx_fifo[7], pl022_state),
+        VMSTATE_END_OF_LIST()
     }
-
-    return 0;
-}
+};
 
 static int pl022_init(SysBusDevice *dev)
 {
@@ -300,7 +288,7 @@ static int pl022_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
-    register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_pl022, s);
     return 0;
 }
 
commit 293c16aa372fcdfed3be460cf657aced56327195
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 03:03:11 2010 +0100

    vmstate: port stellaris sys
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 00efb36..11d618d 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -604,58 +604,37 @@ static void ssys_reset(void *opaque)
     s->dcgc[0] = 1;
 }
 
-static void ssys_save(QEMUFile *f, void *opaque)
+static int stellaris_sys_post_load(void *opaque, int version_id)
 {
-    ssys_state *s = (ssys_state *)opaque;
-
-    qemu_put_be32(f, s->pborctl);
-    qemu_put_be32(f, s->ldopctl);
-    qemu_put_be32(f, s->int_mask);
-    qemu_put_be32(f, s->int_status);
-    qemu_put_be32(f, s->resc);
-    qemu_put_be32(f, s->rcc);
-    qemu_put_be32(f, s->rcgc[0]);
-    qemu_put_be32(f, s->rcgc[1]);
-    qemu_put_be32(f, s->rcgc[2]);
-    qemu_put_be32(f, s->scgc[0]);
-    qemu_put_be32(f, s->scgc[1]);
-    qemu_put_be32(f, s->scgc[2]);
-    qemu_put_be32(f, s->dcgc[0]);
-    qemu_put_be32(f, s->dcgc[1]);
-    qemu_put_be32(f, s->dcgc[2]);
-    qemu_put_be32(f, s->clkvclr);
-    qemu_put_be32(f, s->ldoarst);
-}
-
-static int ssys_load(QEMUFile *f, void *opaque, int version_id)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
+    ssys_state *s = opaque;
 
-    s->pborctl = qemu_get_be32(f);
-    s->ldopctl = qemu_get_be32(f);
-    s->int_mask = qemu_get_be32(f);
-    s->int_status = qemu_get_be32(f);
-    s->resc = qemu_get_be32(f);
-    s->rcc = qemu_get_be32(f);
-    s->rcgc[0] = qemu_get_be32(f);
-    s->rcgc[1] = qemu_get_be32(f);
-    s->rcgc[2] = qemu_get_be32(f);
-    s->scgc[0] = qemu_get_be32(f);
-    s->scgc[1] = qemu_get_be32(f);
-    s->scgc[2] = qemu_get_be32(f);
-    s->dcgc[0] = qemu_get_be32(f);
-    s->dcgc[1] = qemu_get_be32(f);
-    s->dcgc[2] = qemu_get_be32(f);
-    s->clkvclr = qemu_get_be32(f);
-    s->ldoarst = qemu_get_be32(f);
     ssys_calculate_system_clock(s);
 
     return 0;
 }
 
+static const VMStateDescription vmstate_stellaris_sys = {
+    .name = "stellaris_sys",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = stellaris_sys_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(pborctl, ssys_state),
+        VMSTATE_UINT32(ldopctl, ssys_state),
+        VMSTATE_UINT32(int_mask, ssys_state),
+        VMSTATE_UINT32(int_status, ssys_state),
+        VMSTATE_UINT32(resc, ssys_state),
+        VMSTATE_UINT32(rcc, ssys_state),
+        VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
+        VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
+        VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
+        VMSTATE_UINT32(clkvclr, ssys_state),
+        VMSTATE_UINT32(ldoarst, ssys_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                               stellaris_board_info * board,
                               uint8_t *macaddr)
@@ -675,7 +654,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
                                        DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
-    register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+    vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
     return 0;
 }
 
commit a4dec1d0d423443d3e5a026a1776fb41b33c06eb
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 02:51:29 2010 +0100

    vmstate: port stellaris ssi bus
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index d0b1588..00efb36 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1218,24 +1218,16 @@ static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val)
     return ssi_transfer(s->bus[s->current_dev], val);
 }
 
-static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque)
-{
-    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
-    qemu_put_be32(f, s->current_dev);
-}
-
-static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
-{
-    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->current_dev = qemu_get_be32(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_stellaris_ssi_bus = {
+    .name = "stellaris_ssi_bus",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(current_dev, stellaris_ssi_bus_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int stellaris_ssi_bus_init(SSISlave *dev)
 {
@@ -1245,8 +1237,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
 
-    register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
-                    stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s);
     return 0;
 }
 
commit ff269cd041d33cded58bc734f88456720dcc1864
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 02:48:43 2010 +0100

    vmstate: port stellaris i2c
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/stellaris.c b/hw/stellaris.c
index 7932c24..d0b1588 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -843,36 +843,22 @@ static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
    stellaris_i2c_write
 };
 
-static void stellaris_i2c_save(QEMUFile *f, void *opaque)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    qemu_put_be32(f, s->msa);
-    qemu_put_be32(f, s->mcs);
-    qemu_put_be32(f, s->mdr);
-    qemu_put_be32(f, s->mtpr);
-    qemu_put_be32(f, s->mimr);
-    qemu_put_be32(f, s->mris);
-    qemu_put_be32(f, s->mcr);
-}
-
-static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->msa = qemu_get_be32(f);
-    s->mcs = qemu_get_be32(f);
-    s->mdr = qemu_get_be32(f);
-    s->mtpr = qemu_get_be32(f);
-    s->mimr = qemu_get_be32(f);
-    s->mris = qemu_get_be32(f);
-    s->mcr = qemu_get_be32(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_stellaris_i2c = {
+    .name = "stellaris_i2c",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(msa, stellaris_i2c_state),
+        VMSTATE_UINT32(mcs, stellaris_i2c_state),
+        VMSTATE_UINT32(mdr, stellaris_i2c_state),
+        VMSTATE_UINT32(mtpr, stellaris_i2c_state),
+        VMSTATE_UINT32(mimr, stellaris_i2c_state),
+        VMSTATE_UINT32(mris, stellaris_i2c_state),
+        VMSTATE_UINT32(mcr, stellaris_i2c_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int stellaris_i2c_init(SysBusDevice * dev)
 {
@@ -890,8 +876,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
-    register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
-                    stellaris_i2c_save, stellaris_i2c_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
     return 0;
 }
 
commit 0797226c56ea51a72ebbf7dcecfd2c1e44147cf0
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 02:17:33 2010 +0100

    vmstate: port armv7m nvic
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index ffe16b8..d06eec9 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -365,30 +365,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
     }
 }
 
-static void nvic_save(QEMUFile *f, void *opaque)
-{
-    nvic_state *s = (nvic_state *)opaque;
-
-    qemu_put_be32(f, s->systick.control);
-    qemu_put_be32(f, s->systick.reload);
-    qemu_put_be64(f, s->systick.tick);
-    qemu_put_timer(f, s->systick.timer);
-}
-
-static int nvic_load(QEMUFile *f, void *opaque, int version_id)
-{
-    nvic_state *s = (nvic_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->systick.control = qemu_get_be32(f);
-    s->systick.reload = qemu_get_be32(f);
-    s->systick.tick = qemu_get_be64(f);
-    qemu_get_timer(f, s->systick.timer);
-
-    return 0;
-}
+static const VMStateDescription vmstate_nvic = {
+    .name = "armv7m_nvic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(systick.control, nvic_state),
+        VMSTATE_UINT32(systick.reload, nvic_state),
+        VMSTATE_INT64(systick.tick, nvic_state),
+        VMSTATE_TIMER(systick.timer, nvic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int armv7m_nvic_init(SysBusDevice *dev)
 {
@@ -397,7 +386,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
     gic_init(&s->gic);
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
commit 02b687579578a1df9f5733023544c21a8446d3a3
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 01:50:33 2010 +0100

    vmstate: port pl011
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pl011.c b/hw/pl011.c
index 77f0dbf..3b94b14 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -235,56 +235,30 @@ static CPUWriteMemoryFunc * const pl011_writefn[] = {
    pl011_write
 };
 
-static void pl011_save(QEMUFile *f, void *opaque)
-{
-    pl011_state *s = (pl011_state *)opaque;
-    int i;
-
-    qemu_put_be32(f, s->readbuff);
-    qemu_put_be32(f, s->flags);
-    qemu_put_be32(f, s->lcr);
-    qemu_put_be32(f, s->cr);
-    qemu_put_be32(f, s->dmacr);
-    qemu_put_be32(f, s->int_enabled);
-    qemu_put_be32(f, s->int_level);
-    for (i = 0; i < 16; i++)
-        qemu_put_be32(f, s->read_fifo[i]);
-    qemu_put_be32(f, s->ilpr);
-    qemu_put_be32(f, s->ibrd);
-    qemu_put_be32(f, s->fbrd);
-    qemu_put_be32(f, s->ifl);
-    qemu_put_be32(f, s->read_pos);
-    qemu_put_be32(f, s->read_count);
-    qemu_put_be32(f, s->read_trigger);
-}
-
-static int pl011_load(QEMUFile *f, void *opaque, int version_id)
-{
-    pl011_state *s = (pl011_state *)opaque;
-    int i;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->readbuff = qemu_get_be32(f);
-    s->flags = qemu_get_be32(f);
-    s->lcr = qemu_get_be32(f);
-    s->cr = qemu_get_be32(f);
-    s->dmacr = qemu_get_be32(f);
-    s->int_enabled = qemu_get_be32(f);
-    s->int_level = qemu_get_be32(f);
-    for (i = 0; i < 16; i++)
-        s->read_fifo[i] = qemu_get_be32(f);
-    s->ilpr = qemu_get_be32(f);
-    s->ibrd = qemu_get_be32(f);
-    s->fbrd = qemu_get_be32(f);
-    s->ifl = qemu_get_be32(f);
-    s->read_pos = qemu_get_be32(f);
-    s->read_count = qemu_get_be32(f);
-    s->read_trigger = qemu_get_be32(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pl011 = {
+    .name = "pl011",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(readbuff, pl011_state),
+        VMSTATE_UINT32(flags, pl011_state),
+        VMSTATE_UINT32(lcr, pl011_state),
+        VMSTATE_UINT32(cr, pl011_state),
+        VMSTATE_UINT32(dmacr, pl011_state),
+        VMSTATE_UINT32(int_enabled, pl011_state),
+        VMSTATE_UINT32(int_level, pl011_state),
+        VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16),
+        VMSTATE_UINT32(ilpr, pl011_state),
+        VMSTATE_UINT32(ibrd, pl011_state),
+        VMSTATE_UINT32(fbrd, pl011_state),
+        VMSTATE_UINT32(ifl, pl011_state),
+        VMSTATE_INT32(read_pos, pl011_state),
+        VMSTATE_INT32(read_count, pl011_state),
+        VMSTATE_INT32(read_trigger, pl011_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int pl011_init(SysBusDevice *dev, const unsigned char *id)
 {
@@ -307,7 +281,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
         qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
                               pl011_event, s);
     }
-    register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
     return 0;
 }
 
commit 25f5a1b7df5b55aa850326673e30560f294577c7
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 01:06:08 2010 +0100

    vmstate: port pxa2xx_keypad
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index d77dbf1..10ef154 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -289,40 +289,22 @@ static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = {
     pxa2xx_keypad_write
 };
 
-static void pxa2xx_keypad_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
-    qemu_put_be32s(f, &s->kpc);
-    qemu_put_be32s(f, &s->kpdk);
-    qemu_put_be32s(f, &s->kprec);
-    qemu_put_be32s(f, &s->kpmk);
-    qemu_put_be32s(f, &s->kpas);
-    qemu_put_be32s(f, &s->kpasmkp[0]);
-    qemu_put_be32s(f, &s->kpasmkp[1]);
-    qemu_put_be32s(f, &s->kpasmkp[2]);
-    qemu_put_be32s(f, &s->kpasmkp[3]);
-    qemu_put_be32s(f, &s->kpkdi);
-
-}
-
-static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
-    qemu_get_be32s(f, &s->kpc);
-    qemu_get_be32s(f, &s->kpdk);
-    qemu_get_be32s(f, &s->kprec);
-    qemu_get_be32s(f, &s->kpmk);
-    qemu_get_be32s(f, &s->kpas);
-    qemu_get_be32s(f, &s->kpasmkp[0]);
-    qemu_get_be32s(f, &s->kpasmkp[1]);
-    qemu_get_be32s(f, &s->kpasmkp[2]);
-    qemu_get_be32s(f, &s->kpasmkp[3]);
-    qemu_get_be32s(f, &s->kpkdi);
-
-    return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_keypad = {
+    .name = "pxa2xx_keypad",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(kpc, PXA2xxKeyPadState),
+        VMSTATE_UINT32(kpdk, PXA2xxKeyPadState),
+        VMSTATE_UINT32(kprec, PXA2xxKeyPadState),
+        VMSTATE_UINT32(kpmk, PXA2xxKeyPadState),
+        VMSTATE_UINT32(kpas, PXA2xxKeyPadState),
+        VMSTATE_UINT32_ARRAY(kpasmkp, PXA2xxKeyPadState, 4),
+        VMSTATE_UINT32(kpkdi, PXA2xxKeyPadState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
         qemu_irq irq)
@@ -337,8 +319,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
                     pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
-    register_savevm(NULL, "pxa2xx_keypad", 0, 0,
-                    pxa2xx_keypad_save, pxa2xx_keypad_load, s);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s);
 
     return s;
 }
commit 4ba673ce628ea554a0c095c432813debe6ec339a
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 00:44:28 2010 +0100

    vmstate: port syborg_rtc
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 16d8f9e..69f6ccf 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -102,26 +102,17 @@ static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = {
     syborg_rtc_write
 };
 
-static void syborg_rtc_save(QEMUFile *f, void *opaque)
-{
-    SyborgRTCState *s = opaque;
-
-    qemu_put_be64(f, s->offset);
-    qemu_put_be64(f, s->data);
-}
-
-static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgRTCState *s = opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->offset = qemu_get_be64(f);
-    s->data = qemu_get_be64(f);
-
-    return 0;
-}
+static const VMStateDescription vmstate_syborg_rtc = {
+    .name = "syborg_keyboard",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT64(offset, SyborgRTCState),
+        VMSTATE_INT64(data, SyborgRTCState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int syborg_rtc_init(SysBusDevice *dev)
 {
@@ -137,8 +128,7 @@ static int syborg_rtc_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
 
-    register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
-                    syborg_rtc_save, syborg_rtc_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s);
     return 0;
 }
 
commit 852f771ec9e5cb5e57b4023209f37dd331d5dbdd
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 23:51:14 2010 +0100

    vmstate: port pmtimer
    
    It was a half conversion.  Finish it.
    enabled can only get values of 0, 1 or 2, was declared as an int but
    sent as an unint8_t, change its type.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/hw.h b/hw/hw.h
index 1b09039..56447a7 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -689,6 +689,17 @@ extern const VMStateDescription vmstate_usb_device;
     .offset     = vmstate_offset_macaddr(_state, _field),            \
 }
 
+extern const VMStateDescription vmstate_ptimer;
+
+#define VMSTATE_PTIMER(_field, _state) {                             \
+    .name       = (stringify(_field)),                               \
+    .version_id = (1),                                               \
+    .vmsd       = &vmstate_ptimer,                                   \
+    .size       = sizeof(ptimer_state *),                            \
+    .flags      = VMS_STRUCT|VMS_POINTER,                            \
+    .offset     = vmstate_offset_pointer(_state, _field, ptimer_state), \
+}
+
 /* _f : field name
    _f_n : num of elements field_name
    _n : num of elements
@@ -784,12 +795,6 @@ extern const VMStateDescription vmstate_usb_device;
 #define VMSTATE_TIMER_ARRAY(_f, _s, _n)                              \
     VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
 
-#define VMSTATE_PTIMER_V(_f, _s, _v)                                  \
-    VMSTATE_POINTER(_f, _s, _v, vmstate_info_ptimer, ptimer_state *)
-
-#define VMSTATE_PTIMER(_f, _s)                                        \
-    VMSTATE_PTIMER_V(_f, _s, 0)
-
 #define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool)
 
diff --git a/hw/ptimer.c b/hw/ptimer.c
index e68c1d1..47964a6 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -11,7 +11,7 @@
 
 struct ptimer_state
 {
-    int enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot.  */
+    uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot.  */
     uint64_t limit;
     uint64_t delta;
     uint32_t period_frac;
@@ -188,49 +188,22 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
     }
 }
 
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s)
-{
-    qemu_put_byte(f, s->enabled);
-    qemu_put_be64s(f, &s->limit);
-    qemu_put_be64s(f, &s->delta);
-    qemu_put_be32s(f, &s->period_frac);
-    qemu_put_sbe64s(f, &s->period);
-    qemu_put_sbe64s(f, &s->last_event);
-    qemu_put_sbe64s(f, &s->next_event);
-    qemu_put_timer(f, s->timer);
-}
-
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s)
-{
-    s->enabled = qemu_get_byte(f);
-    qemu_get_be64s(f, &s->limit);
-    qemu_get_be64s(f, &s->delta);
-    qemu_get_be32s(f, &s->period_frac);
-    qemu_get_sbe64s(f, &s->period);
-    qemu_get_sbe64s(f, &s->last_event);
-    qemu_get_sbe64s(f, &s->next_event);
-    qemu_get_timer(f, s->timer);
-}
-
-static int get_ptimer(QEMUFile *f, void *pv, size_t size)
-{
-    ptimer_state *v = pv;
-
-    qemu_get_ptimer(f, v);
-    return 0;
-}
-
-static void put_ptimer(QEMUFile *f, void *pv, size_t size)
-{
-    ptimer_state *v = pv;
-
-    qemu_put_ptimer(f, v);
-}
-
-const VMStateInfo vmstate_info_ptimer = {
+const VMStateDescription vmstate_ptimer = {
     .name = "ptimer",
-    .get  = get_ptimer,
-    .put  = put_ptimer,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(enabled, ptimer_state),
+        VMSTATE_UINT64(limit, ptimer_state),
+        VMSTATE_UINT64(delta, ptimer_state),
+        VMSTATE_UINT32(period_frac, ptimer_state),
+        VMSTATE_INT64(period, ptimer_state),
+        VMSTATE_INT64(last_event, ptimer_state),
+        VMSTATE_INT64(next_event, ptimer_state),
+        VMSTATE_TIMER(timer, ptimer_state),
+        VMSTATE_END_OF_LIST()
+    }
 };
 
 ptimer_state *ptimer_init(QEMUBH *bh)
diff --git a/qemu-timer.h b/qemu-timer.h
index bbc3452..2cacf65 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -144,8 +144,6 @@ uint64_t ptimer_get_count(ptimer_state *s);
 void ptimer_set_count(ptimer_state *s, uint64_t count);
 void ptimer_run(ptimer_state *s, int oneshot);
 void ptimer_stop(ptimer_state *s);
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
 
 /* icount */
 int64_t qemu_icount_round(int64_t count);
commit 22a3faf507a9de2fab8988daf39ff41d09419bec
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 23:18:59 2010 +0100

    vmstate: port sysborg_timer
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index cedcd8e..50c813e 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -174,34 +174,21 @@ static CPUWriteMemoryFunc * const syborg_timer_writefn[] = {
     syborg_timer_write
 };
 
-static void syborg_timer_save(QEMUFile *f, void *opaque)
-{
-    SyborgTimerState *s = opaque;
-
-    qemu_put_be32(f, s->running);
-    qemu_put_be32(f, s->oneshot);
-    qemu_put_be32(f, s->limit);
-    qemu_put_be32(f, s->int_level);
-    qemu_put_be32(f, s->int_enabled);
-    qemu_put_ptimer(f, s->timer);
-}
-
-static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SyborgTimerState *s = opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->running = qemu_get_be32(f);
-    s->oneshot = qemu_get_be32(f);
-    s->limit = qemu_get_be32(f);
-    s->int_level = qemu_get_be32(f);
-    s->int_enabled = qemu_get_be32(f);
-    qemu_get_ptimer(f, s->timer);
-
-    return 0;
-}
+static const VMStateDescription vmstate_syborg_timer = {
+    .name = "syborg_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(running, SyborgTimerState),
+        VMSTATE_INT32(oneshot, SyborgTimerState),
+        VMSTATE_UINT32(limit, SyborgTimerState),
+        VMSTATE_UINT32(int_level, SyborgTimerState),
+        VMSTATE_UINT32(int_enabled, SyborgTimerState),
+        VMSTATE_PTIMER(timer, SyborgTimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int syborg_timer_init(SysBusDevice *dev)
 {
@@ -222,8 +209,7 @@ static int syborg_timer_init(SysBusDevice *dev)
     bh = qemu_bh_new(syborg_timer_tick, s);
     s->timer = ptimer_init(bh);
     ptimer_set_freq(s->timer, s->freq);
-    register_savevm(&dev->qdev, "syborg_timer", -1, 1,
-                    syborg_timer_save, syborg_timer_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s);
     return 0;
 }
 
commit eecd33a57895a579bd4d2270b1bc758b608ae5a4
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 23:15:41 2010 +0100

    vmstate: port arm_timer
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index cfd1ebe..dac9e70 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -140,28 +140,19 @@ static void arm_timer_tick(void *opaque)
     arm_timer_update(s);
 }
 
-static void arm_timer_save(QEMUFile *f, void *opaque)
-{
-    arm_timer_state *s = (arm_timer_state *)opaque;
-    qemu_put_be32(f, s->control);
-    qemu_put_be32(f, s->limit);
-    qemu_put_be32(f, s->int_level);
-    qemu_put_ptimer(f, s->timer);
-}
-
-static int arm_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
-    arm_timer_state *s = (arm_timer_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->control = qemu_get_be32(f);
-    s->limit = qemu_get_be32(f);
-    s->int_level = qemu_get_be32(f);
-    qemu_get_ptimer(f, s->timer);
-    return 0;
-}
+static const VMStateDescription vmstate_arm_timer = {
+    .name = "arm_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(control, arm_timer_state),
+        VMSTATE_UINT32(limit, arm_timer_state),
+        VMSTATE_INT32(int_level, arm_timer_state),
+        VMSTATE_PTIMER(timer, arm_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static arm_timer_state *arm_timer_init(uint32_t freq)
 {
@@ -174,7 +165,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
 
     bh = qemu_bh_new(arm_timer_tick, s);
     s->timer = ptimer_init(bh);
-    register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+    vmstate_register(NULL, -1, &vmstate_arm_timer, s);
     return s;
 }
 
commit 81986ac4b66af8005fbe79558c319ba6a38561c2
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 23:12:32 2010 +0100

    vmstate: port arm sp804
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 82f05de..cfd1ebe 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -235,24 +235,17 @@ static CPUWriteMemoryFunc * const sp804_writefn[] = {
    sp804_write
 };
 
-static void sp804_save(QEMUFile *f, void *opaque)
-{
-    sp804_state *s = (sp804_state *)opaque;
-    qemu_put_be32(f, s->level[0]);
-    qemu_put_be32(f, s->level[1]);
-}
 
-static int sp804_load(QEMUFile *f, void *opaque, int version_id)
-{
-    sp804_state *s = (sp804_state *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    s->level[0] = qemu_get_be32(f);
-    s->level[1] = qemu_get_be32(f);
-    return 0;
-}
+static const VMStateDescription vmstate_sp804 = {
+    .name = "sp804",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32_ARRAY(level, sp804_state, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int sp804_init(SysBusDevice *dev)
 {
@@ -271,7 +264,7 @@ static int sp804_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(sp804_readfn,
                                        sp804_writefn, s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
+    vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
     return 0;
 }
 
commit c7298ab251019b33d55a2ec9ff1880a9aabe33f8
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 23:02:56 2010 +0100

    vmstate: port mipsnet
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index c5e54ff..26aad51 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -202,44 +202,29 @@ static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-static void mipsnet_save(QEMUFile *f, void *opaque)
-{
-    MIPSnetState *s = opaque;
-
-    qemu_put_be32s(f, &s->busy);
-    qemu_put_be32s(f, &s->rx_count);
-    qemu_put_be32s(f, &s->rx_read);
-    qemu_put_be32s(f, &s->tx_count);
-    qemu_put_be32s(f, &s->tx_written);
-    qemu_put_be32s(f, &s->intctl);
-    qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
-    qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-}
-
-static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
-{
-    MIPSnetState *s = opaque;
-
-    if (version_id > 0)
-        return -EINVAL;
-
-    qemu_get_be32s(f, &s->busy);
-    qemu_get_be32s(f, &s->rx_count);
-    qemu_get_be32s(f, &s->rx_read);
-    qemu_get_be32s(f, &s->tx_count);
-    qemu_get_be32s(f, &s->tx_written);
-    qemu_get_be32s(f, &s->intctl);
-    qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
-    qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-
-    return 0;
-}
+static const VMStateDescription vmstate_mipsnet = {
+    .name = "mipsnet",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(busy, MIPSnetState),
+        VMSTATE_UINT32(rx_count, MIPSnetState),
+        VMSTATE_UINT32(rx_read, MIPSnetState),
+        VMSTATE_UINT32(tx_count, MIPSnetState),
+        VMSTATE_UINT32(tx_written, MIPSnetState),
+        VMSTATE_UINT32(intctl, MIPSnetState),
+        VMSTATE_BUFFER(rx_buffer, MIPSnetState),
+        VMSTATE_BUFFER(tx_buffer, MIPSnetState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void mipsnet_cleanup(VLANClientState *nc)
 {
     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    unregister_savevm(NULL, "mipsnet", s);
+    vmstate_unregister(NULL, &vmstate_mipsnet, s);
 
     isa_unassign_ioport(s->io_base, 36);
 
@@ -284,5 +269,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
     }
 
     mipsnet_reset(s);
-    register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+    vmstate_register(NULL, 0, &vmstate_mipsnet, s);
 }
commit fd484ae494bbb38f832fb89a89c979ca6790b531
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Dec 2 00:16:33 2010 +0100

    vmstate: port m48t59
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/m48t59.c b/hw/m48t59.c
index 9f39d6b..537c0f7 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -585,28 +585,18 @@ static CPUReadMemoryFunc * const nvram_read[] = {
     &nvram_readl,
 };
 
-static void m48t59_save(QEMUFile *f, void *opaque)
-{
-    M48t59State *s = opaque;
-
-    qemu_put_8s(f, &s->lock);
-    qemu_put_be16s(f, &s->addr);
-    qemu_put_buffer(f, s->buffer, s->size);
-}
-
-static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
-{
-    M48t59State *s = opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    qemu_get_8s(f, &s->lock);
-    qemu_get_be16s(f, &s->addr);
-    qemu_get_buffer(f, s->buffer, s->size);
-
-    return 0;
-}
+static const VMStateDescription vmstate_m48t59 = {
+    .name = "m48t59",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(lock, M48t59State),
+        VMSTATE_UINT16(addr, M48t59State),
+        VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void m48t59_reset_common(M48t59State *NVRAM)
 {
@@ -696,7 +686,7 @@ static void m48t59_init_common(M48t59State *s)
     }
     qemu_get_timedate(&s->alarm, 0);
 
-    register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
+    vmstate_register(NULL, -1, &vmstate_m48t59, s);
 }
 
 static int m48t59_init_isa1(ISADevice *dev)
commit aefe2129315c023413e7780d962016bda19f7f3a
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 22:03:06 2010 +0100

    vmstate: port ads7846
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/ads7846.c b/hw/ads7846.c
index b3bbeaf..9c58a5f 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -105,35 +105,30 @@ static void ads7846_ts_event(void *opaque,
     }
 }
 
-static void ads7846_save(QEMUFile *f, void *opaque)
+static int ads7856_post_load(void *opaque, int version_id)
 {
-    ADS7846State *s = (ADS7846State *) opaque;
-    int i;
-
-    for (i = 0; i < 8; i ++)
-        qemu_put_be32(f, s->input[i]);
-    qemu_put_be32(f, s->noise);
-    qemu_put_be32(f, s->cycle);
-    qemu_put_be32(f, s->output);
-}
-
-static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
-{
-    ADS7846State *s = (ADS7846State *) opaque;
-    int i;
-
-    for (i = 0; i < 8; i ++)
-        s->input[i] = qemu_get_be32(f);
-    s->noise = qemu_get_be32(f);
-    s->cycle = qemu_get_be32(f);
-    s->output = qemu_get_be32(f);
+    ADS7846State *s = opaque;
 
     s->pressure = 0;
     ads7846_int_update(s);
-
     return 0;
 }
 
+static const VMStateDescription vmstate_ads7846 = {
+    .name = "ads7846",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = ads7856_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32_ARRAY(input, ADS7846State, 8),
+        VMSTATE_INT32(noise, ADS7846State),
+        VMSTATE_INT32(cycle, ADS7846State),
+        VMSTATE_INT32(output, ADS7846State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static int ads7846_init(SSISlave *dev)
 {
     ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
@@ -151,7 +146,7 @@ static int ads7846_init(SSISlave *dev)
 
     ads7846_int_update(s);
 
-    register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
+    vmstate_register(NULL, -1, &vmstate_ads7846, s);
     return 0;
 }
 
commit 2b2cd5928d9fcad9f1941225f8b9598a2a954e11
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 21:56:35 2010 +0100

    vmstate: port adb_mouse
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/adb.c b/hw/adb.c
index fbf5080..7499cdc 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -427,32 +427,20 @@ static int adb_mouse_reset(ADBDevice *d)
     return 0;
 }
 
-static void adb_mouse_save(QEMUFile *f, void *opaque)
-{
-    MouseState *s = (MouseState *)opaque;
-
-    qemu_put_sbe32s(f, &s->buttons_state);
-    qemu_put_sbe32s(f, &s->last_buttons_state);
-    qemu_put_sbe32s(f, &s->dx);
-    qemu_put_sbe32s(f, &s->dy);
-    qemu_put_sbe32s(f, &s->dz);
-}
-
-static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
-{
-    MouseState *s = (MouseState *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    qemu_get_sbe32s(f, &s->buttons_state);
-    qemu_get_sbe32s(f, &s->last_buttons_state);
-    qemu_get_sbe32s(f, &s->dx);
-    qemu_get_sbe32s(f, &s->dy);
-    qemu_get_sbe32s(f, &s->dz);
-
-    return 0;
-}
+static const VMStateDescription vmstate_adb_mouse = {
+    .name = "adb_mouse",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(buttons_state, MouseState),
+        VMSTATE_INT32(last_buttons_state, MouseState),
+        VMSTATE_INT32(dx, MouseState),
+        VMSTATE_INT32(dy, MouseState),
+        VMSTATE_INT32(dz, MouseState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 void adb_mouse_init(ADBBusState *bus)
 {
@@ -463,6 +451,5 @@ void adb_mouse_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
-    register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
-                    adb_mouse_load, s);
+    vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
 }
commit 1f1f0600aa8a233ceb1b90e9f47386849bdb11ed
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Dec 1 21:54:04 2010 +0100

    vmstate: port adb_kbd
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/adb.c b/hw/adb.c
index 99b30f6..fbf5080 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -261,30 +261,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
     return olen;
 }
 
-static void adb_kbd_save(QEMUFile *f, void *opaque)
-{
-    KBDState *s = (KBDState *)opaque;
-
-    qemu_put_buffer(f, s->data, sizeof(s->data));
-    qemu_put_sbe32s(f, &s->rptr);
-    qemu_put_sbe32s(f, &s->wptr);
-    qemu_put_sbe32s(f, &s->count);
-}
-
-static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
-{
-    KBDState *s = (KBDState *)opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    qemu_get_buffer(f, s->data, sizeof(s->data));
-    qemu_get_sbe32s(f, &s->rptr);
-    qemu_get_sbe32s(f, &s->wptr);
-    qemu_get_sbe32s(f, &s->count);
-
-    return 0;
-}
+static const VMStateDescription vmstate_adb_kbd = {
+    .name = "adb_kbd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_BUFFER(data, KBDState),
+        VMSTATE_INT32(rptr, KBDState),
+        VMSTATE_INT32(wptr, KBDState),
+        VMSTATE_INT32(count, KBDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static int adb_kbd_reset(ADBDevice *d)
 {
@@ -305,8 +294,7 @@ void adb_kbd_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                             adb_kbd_reset, s);
     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
-    register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
-                    adb_kbd_load, s);
+    vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
 }
 
 /***************************************************************/
commit ec444452b8753a372de30b22d9b4765a799db612
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 19 17:30:55 2011 +0100

    target-arm: Set Invalid flag for NaN in float-to-int conversions
    
    When we catch the special case of an input NaN in ARM float to int
    helper functions, set the Invalid flag as well as returning the
    correct result.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index bf84335..62ae72e 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2551,6 +2551,7 @@ float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env)
 uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float32_to_uint32(x, &env->vfp.fp_status);
@@ -2559,6 +2560,7 @@ uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
 uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float64_to_uint32(x, &env->vfp.fp_status);
@@ -2567,6 +2569,7 @@ uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
 uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float32_to_int32(x, &env->vfp.fp_status);
@@ -2575,6 +2578,7 @@ uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
 uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float64_to_int32(x, &env->vfp.fp_status);
@@ -2583,6 +2587,7 @@ uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
 uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2591,6 +2596,7 @@ uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
 uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2599,6 +2605,7 @@ uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
 uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float32_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2607,6 +2614,7 @@ uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
 uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
+        float_raise(float_flag_invalid, &env->vfp.fp_status);
         return 0;
     }
     return float64_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2645,6 +2653,7 @@ uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \
 { \
     float##fsz tmp; \
     if (float##fsz##_is_any_nan(x)) { \
+        float_raise(float_flag_invalid, &env->vfp.fp_status); \
         return 0; \
     } \
     tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \
commit 756ba3b0127fea2bfb538d256c76f19aec126732
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 19 16:32:34 2011 +0100

    hw/arm_boot.c: move initrd load address up to accommodate large kernels
    
    Newer kernels are large enough that they can overlap the address
    where qemu places the initrd. Move the initrd up so that there is
    enough space for the kernel again.
    
    Unfortunately it's not possible to automatically determine the
    size of the kernel if it is compressed, so this is the best we
    can do.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 41e99d1..bfac982 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -15,7 +15,7 @@
 
 #define KERNEL_ARGS_ADDR 0x100
 #define KERNEL_LOAD_ADDR 0x00010000
-#define INITRD_LOAD_ADDR 0x00800000
+#define INITRD_LOAD_ADDR 0x00d00000
 
 /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
 static uint32_t bootloader[] = {
commit c64b21d519a6ecae12f65625fa60f3035ed88644
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Tue Apr 19 18:56:46 2011 +0400

    Basic implementation of Sharp Zaurus SL-5500 collie PDA
    
    Add very basic implementation of collie PDA emulation. The system lacks
    LoCoMo and graphics/sound emulation. Linux kernel boots up to mounting
    rootfs (theoretically it can be provided in pflash images).
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile.target b/Makefile.target
index 9e4cfc0..0e0ef36 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -353,6 +353,7 @@ obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
 obj-arm-y += syborg_virtio.o
 obj-arm-y += vexpress.o
 obj-arm-y += strongarm.o
+obj-arm-y += collie.o
 
 obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
diff --git a/hw/collie.c b/hw/collie.c
new file mode 100644
index 0000000..156404d
--- /dev/null
+++ b/hw/collie.c
@@ -0,0 +1,69 @@
+/*
+ * SA-1110-based Sharp Zaurus SL-5500 platform.
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * This code is licensed under GNU GPL v2.
+ */
+#include "hw.h"
+#include "sysbus.h"
+#include "boards.h"
+#include "devices.h"
+#include "strongarm.h"
+#include "arm-misc.h"
+#include "flash.h"
+#include "blockdev.h"
+
+static struct arm_boot_info collie_binfo = {
+    .loader_start = SA_SDCS0,
+    .ram_size = 0x20000000,
+};
+
+static void collie_init(ram_addr_t ram_size,
+                const char *boot_device,
+                const char *kernel_filename, const char *kernel_cmdline,
+                const char *initrd_filename, const char *cpu_model)
+{
+    StrongARMState *s;
+    DriveInfo *dinfo;
+    ram_addr_t phys_flash;
+
+    if (!cpu_model) {
+        cpu_model = "sa1110";
+    }
+
+    s = sa1110_init(collie_binfo.ram_size, cpu_model);
+
+    phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(SA_CS0, phys_flash,
+                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+    phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
+    dinfo = drive_get(IF_PFLASH, 0, 1);
+    pflash_cfi01_register(SA_CS1, phys_flash,
+                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+    sysbus_create_simple("scoop", 0x40800000, NULL);
+
+    collie_binfo.kernel_filename = kernel_filename;
+    collie_binfo.kernel_cmdline = kernel_cmdline;
+    collie_binfo.initrd_filename = initrd_filename;
+    collie_binfo.board_id = 0x208;
+    arm_load_kernel(s->env, &collie_binfo);
+}
+
+static QEMUMachine collie_machine = {
+    .name = "collie",
+    .desc = "Collie PDA (SA-1110)",
+    .init = collie_init,
+};
+
+static void collie_machine_init(void)
+{
+    qemu_register_machine(&collie_machine);
+}
+
+machine_init(collie_machine_init)
commit 5bc95aa2461f3b9f70ecbb2a9ec22f939fc33d6d
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Tue Apr 19 18:56:45 2011 +0400

    Implement basic part of SA-1110/SA-1100
    
    Basic implementation of DEC/Intel SA-1100/SA-1110 chips emulation.
    Implemented:
     - IRQs
     - GPIO
     - PPC
     - RTC
     - UARTs (no IrDA/etc.)
     - OST reused from pxa25x
    
    Everything else is TODO (esp. PM/idle/sleep!) - see the todo in the
    hw/strongarm.c
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile.target b/Makefile.target
index d5761b7..9e4cfc0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -352,6 +352,7 @@ obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
 obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
 obj-arm-y += syborg_virtio.o
 obj-arm-y += vexpress.o
+obj-arm-y += strongarm.o
 
 obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
diff --git a/hw/strongarm.c b/hw/strongarm.c
new file mode 100644
index 0000000..de08bdf
--- /dev/null
+++ b/hw/strongarm.c
@@ -0,0 +1,1598 @@
+/*
+ * StrongARM SA-1100/SA-1110 emulation
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * Largely based on StrongARM emulation:
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * UART code based on QEMU 16550A UART emulation
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2008 Citrix Systems, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "sysbus.h"
+#include "strongarm.h"
+#include "qemu-error.h"
+#include "arm-misc.h"
+#include "sysemu.h"
+#include "ssi.h"
+
+//#define DEBUG
+
+/*
+ TODO
+ - Implement cp15, c14 ?
+ - Implement cp15, c15 !!! (idle used in L)
+ - Implement idle mode handling/DIM
+ - Implement sleep mode/Wake sources
+ - Implement reset control
+ - Implement memory control regs
+ - PCMCIA handling
+ - Maybe support MBGNT/MBREQ
+ - DMA channels
+ - GPCLK
+ - IrDA
+ - MCP
+ - Enhance UART with modem signals
+ */
+
+#ifdef DEBUG
+# define DPRINTF(format, ...) printf(format , ## __VA_ARGS__)
+#else
+# define DPRINTF(format, ...) do { } while (0)
+#endif
+
+static struct {
+    target_phys_addr_t io_base;
+    int irq;
+} sa_serial[] = {
+    { 0x80010000, SA_PIC_UART1 },
+    { 0x80030000, SA_PIC_UART2 },
+    { 0x80050000, SA_PIC_UART3 },
+    { 0, 0 }
+};
+
+/* Interrupt Controller */
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq    irq;
+    qemu_irq    fiq;
+
+    uint32_t pending;
+    uint32_t enabled;
+    uint32_t is_fiq;
+    uint32_t int_idle;
+} StrongARMPICState;
+
+#define ICIP    0x00
+#define ICMR    0x04
+#define ICLR    0x08
+#define ICFP    0x10
+#define ICPR    0x20
+#define ICCR    0x0c
+
+#define SA_PIC_SRCS     32
+
+
+static void strongarm_pic_update(void *opaque)
+{
+    StrongARMPICState *s = opaque;
+
+    /* FIXME: reflect DIM */
+    qemu_set_irq(s->fiq, s->pending & s->enabled &  s->is_fiq);
+    qemu_set_irq(s->irq, s->pending & s->enabled & ~s->is_fiq);
+}
+
+static void strongarm_pic_set_irq(void *opaque, int irq, int level)
+{
+    StrongARMPICState *s = opaque;
+
+    if (level) {
+        s->pending |= 1 << irq;
+    } else {
+        s->pending &= ~(1 << irq);
+    }
+
+    strongarm_pic_update(s);
+}
+
+static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset)
+{
+    StrongARMPICState *s = opaque;
+
+    switch (offset) {
+    case ICIP:
+        return s->pending & ~s->is_fiq & s->enabled;
+    case ICMR:
+        return s->enabled;
+    case ICLR:
+        return s->is_fiq;
+    case ICCR:
+        return s->int_idle == 0;
+    case ICFP:
+        return s->pending & s->is_fiq & s->enabled;
+    case ICPR:
+        return s->pending;
+    default:
+        printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+                        __func__, offset);
+        return 0;
+    }
+}
+
+static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset,
+                uint32_t value)
+{
+    StrongARMPICState *s = opaque;
+
+    switch (offset) {
+    case ICMR:
+        s->enabled = value;
+        break;
+    case ICLR:
+        s->is_fiq = value;
+        break;
+    case ICCR:
+        s->int_idle = (value & 1) ? 0 : ~0;
+        break;
+    default:
+        printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+                        __func__, offset);
+        break;
+    }
+    strongarm_pic_update(s);
+}
+
+static CPUReadMemoryFunc * const strongarm_pic_readfn[] = {
+    strongarm_pic_mem_read,
+    strongarm_pic_mem_read,
+    strongarm_pic_mem_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_pic_writefn[] = {
+    strongarm_pic_mem_write,
+    strongarm_pic_mem_write,
+    strongarm_pic_mem_write,
+};
+
+static int strongarm_pic_initfn(SysBusDevice *dev)
+{
+    StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
+    int iomemtype;
+
+    qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
+    iomemtype = cpu_register_io_memory(strongarm_pic_readfn,
+                    strongarm_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(dev, &s->fiq);
+
+    return 0;
+}
+
+static int strongarm_pic_post_load(void *opaque, int version_id)
+{
+    strongarm_pic_update(opaque);
+    return 0;
+}
+
+static VMStateDescription vmstate_strongarm_pic_regs = {
+    .name = "strongarm_pic",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = strongarm_pic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(pending, StrongARMPICState),
+        VMSTATE_UINT32(enabled, StrongARMPICState),
+        VMSTATE_UINT32(is_fiq, StrongARMPICState),
+        VMSTATE_UINT32(int_idle, StrongARMPICState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_pic_info = {
+    .init       = strongarm_pic_initfn,
+    .qdev.name  = "strongarm_pic",
+    .qdev.desc  = "StrongARM PIC",
+    .qdev.size  = sizeof(StrongARMPICState),
+    .qdev.vmsd  = &vmstate_strongarm_pic_regs,
+};
+
+/* Real-Time Clock */
+#define RTAR 0x00 /* RTC Alarm register */
+#define RCNR 0x04 /* RTC Counter register */
+#define RTTR 0x08 /* RTC Timer Trim register */
+#define RTSR 0x10 /* RTC Status register */
+
+#define RTSR_AL (1 << 0) /* RTC Alarm detected */
+#define RTSR_HZ (1 << 1) /* RTC 1Hz detected */
+#define RTSR_ALE (1 << 2) /* RTC Alarm enable */
+#define RTSR_HZE (1 << 3) /* RTC 1Hz enable */
+
+/* 16 LSB of RTTR are clockdiv for internal trim logic,
+ * trim delete isn't emulated, so
+ * f = 32 768 / (RTTR_trim + 1) */
+
+typedef struct {
+    SysBusDevice busdev;
+    uint32_t rttr;
+    uint32_t rtsr;
+    uint32_t rtar;
+    uint32_t last_rcnr;
+    int64_t last_hz;
+    QEMUTimer *rtc_alarm;
+    QEMUTimer *rtc_hz;
+    qemu_irq rtc_irq;
+    qemu_irq rtc_hz_irq;
+} StrongARMRTCState;
+
+static inline void strongarm_rtc_int_update(StrongARMRTCState *s)
+{
+    qemu_set_irq(s->rtc_irq, s->rtsr & RTSR_AL);
+    qemu_set_irq(s->rtc_hz_irq, s->rtsr & RTSR_HZ);
+}
+
+static void strongarm_rtc_hzupdate(StrongARMRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rt_clock);
+    s->last_rcnr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_hz = rt;
+}
+
+static inline void strongarm_rtc_timer_update(StrongARMRTCState *s)
+{
+    if ((s->rtsr & RTSR_HZE) && !(s->rtsr & RTSR_HZ)) {
+        qemu_mod_timer(s->rtc_hz, s->last_hz + 1000);
+    } else {
+        qemu_del_timer(s->rtc_hz);
+    }
+
+    if ((s->rtsr & RTSR_ALE) && !(s->rtsr & RTSR_AL)) {
+        qemu_mod_timer(s->rtc_alarm, s->last_hz +
+                (((s->rtar - s->last_rcnr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15));
+    } else {
+        qemu_del_timer(s->rtc_alarm);
+    }
+}
+
+static inline void strongarm_rtc_alarm_tick(void *opaque)
+{
+    StrongARMRTCState *s = opaque;
+    s->rtsr |= RTSR_AL;
+    strongarm_rtc_timer_update(s);
+    strongarm_rtc_int_update(s);
+}
+
+static inline void strongarm_rtc_hz_tick(void *opaque)
+{
+    StrongARMRTCState *s = opaque;
+    s->rtsr |= RTSR_HZ;
+    strongarm_rtc_timer_update(s);
+    strongarm_rtc_int_update(s);
+}
+
+static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+    StrongARMRTCState *s = opaque;
+
+    switch (addr) {
+    case RTTR:
+        return s->rttr;
+    case RTSR:
+        return s->rtsr;
+    case RTAR:
+        return s->rtar;
+    case RCNR:
+        return s->last_rcnr +
+                ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+        return 0;
+    }
+}
+
+static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    StrongARMRTCState *s = opaque;
+    uint32_t old_rtsr;
+
+    switch (addr) {
+    case RTTR:
+        strongarm_rtc_hzupdate(s);
+        s->rttr = value;
+        strongarm_rtc_timer_update(s);
+        break;
+
+    case RTSR:
+        old_rtsr = s->rtsr;
+        s->rtsr = (value & (RTSR_ALE | RTSR_HZE)) |
+                  (s->rtsr & ~(value & (RTSR_AL | RTSR_HZ)));
+
+        if (s->rtsr != old_rtsr) {
+            strongarm_rtc_timer_update(s);
+        }
+
+        strongarm_rtc_int_update(s);
+        break;
+
+    case RTAR:
+        s->rtar = value;
+        strongarm_rtc_timer_update(s);
+        break;
+
+    case RCNR:
+        strongarm_rtc_hzupdate(s);
+        s->last_rcnr = value;
+        strongarm_rtc_timer_update(s);
+        break;
+
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+    }
+}
+
+static CPUReadMemoryFunc * const strongarm_rtc_readfn[] = {
+    strongarm_rtc_read,
+    strongarm_rtc_read,
+    strongarm_rtc_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_rtc_writefn[] = {
+    strongarm_rtc_write,
+    strongarm_rtc_write,
+    strongarm_rtc_write,
+};
+
+static int strongarm_rtc_init(SysBusDevice *dev)
+{
+    StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev);
+    struct tm tm;
+    int iomemtype;
+
+    s->rttr = 0x0;
+    s->rtsr = 0;
+
+    qemu_get_timedate(&tm, 0);
+
+    s->last_rcnr = (uint32_t) mktimegm(&tm);
+    s->last_hz = qemu_get_clock_ms(rt_clock);
+
+    s->rtc_alarm = qemu_new_timer_ms(rt_clock, strongarm_rtc_alarm_tick, s);
+    s->rtc_hz = qemu_new_timer_ms(rt_clock, strongarm_rtc_hz_tick, s);
+
+    sysbus_init_irq(dev, &s->rtc_irq);
+    sysbus_init_irq(dev, &s->rtc_hz_irq);
+
+    iomemtype = cpu_register_io_memory(strongarm_rtc_readfn,
+                    strongarm_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, 0x10000, iomemtype);
+
+    return 0;
+}
+
+static void strongarm_rtc_pre_save(void *opaque)
+{
+    StrongARMRTCState *s = opaque;
+
+    strongarm_rtc_hzupdate(s);
+}
+
+static int strongarm_rtc_post_load(void *opaque, int version_id)
+{
+    StrongARMRTCState *s = opaque;
+
+    strongarm_rtc_timer_update(s);
+    strongarm_rtc_int_update(s);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_rtc_regs = {
+    .name = "strongarm-rtc",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save = strongarm_rtc_pre_save,
+    .post_load = strongarm_rtc_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(rttr, StrongARMRTCState),
+        VMSTATE_UINT32(rtsr, StrongARMRTCState),
+        VMSTATE_UINT32(rtar, StrongARMRTCState),
+        VMSTATE_UINT32(last_rcnr, StrongARMRTCState),
+        VMSTATE_INT64(last_hz, StrongARMRTCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_rtc_sysbus_info = {
+    .init       = strongarm_rtc_init,
+    .qdev.name  = "strongarm-rtc",
+    .qdev.desc  = "StrongARM RTC Controller",
+    .qdev.size  = sizeof(StrongARMRTCState),
+    .qdev.vmsd  = &vmstate_strongarm_rtc_regs,
+};
+
+/* GPIO */
+#define GPLR 0x00
+#define GPDR 0x04
+#define GPSR 0x08
+#define GPCR 0x0c
+#define GRER 0x10
+#define GFER 0x14
+#define GEDR 0x18
+#define GAFR 0x1c
+
+typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
+struct StrongARMGPIOInfo {
+    SysBusDevice busdev;
+    qemu_irq handler[28];
+    qemu_irq irqs[11];
+    qemu_irq irqX;
+
+    uint32_t ilevel;
+    uint32_t olevel;
+    uint32_t dir;
+    uint32_t rising;
+    uint32_t falling;
+    uint32_t status;
+    uint32_t gpsr;
+    uint32_t gafr;
+
+    uint32_t prev_level;
+};
+
+
+static void strongarm_gpio_irq_update(StrongARMGPIOInfo *s)
+{
+    int i;
+    for (i = 0; i < 11; i++) {
+        qemu_set_irq(s->irqs[i], s->status & (1 << i));
+    }
+
+    qemu_set_irq(s->irqX, (s->status & ~0x7ff));
+}
+
+static void strongarm_gpio_set(void *opaque, int line, int level)
+{
+    StrongARMGPIOInfo *s = opaque;
+    uint32_t mask;
+
+    mask = 1 << line;
+
+    if (level) {
+        s->status |= s->rising & mask &
+                ~s->ilevel & ~s->dir;
+        s->ilevel |= mask;
+    } else {
+        s->status |= s->falling & mask &
+                s->ilevel & ~s->dir;
+        s->ilevel &= ~mask;
+    }
+
+    if (s->status & mask) {
+        strongarm_gpio_irq_update(s);
+    }
+}
+
+static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s)
+{
+    uint32_t level, diff;
+    int bit;
+
+    level = s->olevel & s->dir;
+
+    for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+        bit = ffs(diff) - 1;
+        qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+    }
+
+    s->prev_level = level;
+}
+
+static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset)
+{
+    StrongARMGPIOInfo *s = opaque;
+
+    switch (offset) {
+    case GPDR:        /* GPIO Pin-Direction registers */
+        return s->dir;
+
+    case GPSR:        /* GPIO Pin-Output Set registers */
+        DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+                        __func__, offset);
+        return s->gpsr;    /* Return last written value.  */
+
+    case GPCR:        /* GPIO Pin-Output Clear registers */
+        DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+                        __func__, offset);
+        return 31337;        /* Specified as unpredictable in the docs.  */
+
+    case GRER:        /* GPIO Rising-Edge Detect Enable registers */
+        return s->rising;
+
+    case GFER:        /* GPIO Falling-Edge Detect Enable registers */
+        return s->falling;
+
+    case GAFR:        /* GPIO Alternate Function registers */
+        return s->gafr;
+
+    case GPLR:        /* GPIO Pin-Level registers */
+        return (s->olevel & s->dir) |
+               (s->ilevel & ~s->dir);
+
+    case GEDR:        /* GPIO Edge Detect Status registers */
+        return s->status;
+
+    default:
+        printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+    }
+
+    return 0;
+}
+
+static void strongarm_gpio_write(void *opaque,
+                target_phys_addr_t offset, uint32_t value)
+{
+    StrongARMGPIOInfo *s = opaque;
+
+    switch (offset) {
+    case GPDR:        /* GPIO Pin-Direction registers */
+        s->dir = value;
+        strongarm_gpio_handler_update(s);
+        break;
+
+    case GPSR:        /* GPIO Pin-Output Set registers */
+        s->olevel |= value;
+        strongarm_gpio_handler_update(s);
+        s->gpsr = value;
+        break;
+
+    case GPCR:        /* GPIO Pin-Output Clear registers */
+        s->olevel &= ~value;
+        strongarm_gpio_handler_update(s);
+        break;
+
+    case GRER:        /* GPIO Rising-Edge Detect Enable registers */
+        s->rising = value;
+        break;
+
+    case GFER:        /* GPIO Falling-Edge Detect Enable registers */
+        s->falling = value;
+        break;
+
+    case GAFR:        /* GPIO Alternate Function registers */
+        s->gafr = value;
+        break;
+
+    case GEDR:        /* GPIO Edge Detect Status registers */
+        s->status &= ~value;
+        strongarm_gpio_irq_update(s);
+        break;
+
+    default:
+        printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+    }
+}
+
+static CPUReadMemoryFunc * const strongarm_gpio_readfn[] = {
+    strongarm_gpio_read,
+    strongarm_gpio_read,
+    strongarm_gpio_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_gpio_writefn[] = {
+    strongarm_gpio_write,
+    strongarm_gpio_write,
+    strongarm_gpio_write
+};
+
+static DeviceState *strongarm_gpio_init(target_phys_addr_t base,
+                DeviceState *pic)
+{
+    DeviceState *dev;
+    int i;
+
+    dev = qdev_create(NULL, "strongarm-gpio");
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    for (i = 0; i < 12; i++)
+        sysbus_connect_irq(sysbus_from_qdev(dev), i,
+                    qdev_get_gpio_in(pic, SA_PIC_GPIO0_EDGE + i));
+
+    return dev;
+}
+
+static int strongarm_gpio_initfn(SysBusDevice *dev)
+{
+    int iomemtype;
+    StrongARMGPIOInfo *s;
+    int i;
+
+    s = FROM_SYSBUS(StrongARMGPIOInfo, dev);
+
+    qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
+    qdev_init_gpio_out(&dev->qdev, s->handler, 28);
+
+    iomemtype = cpu_register_io_memory(strongarm_gpio_readfn,
+                    strongarm_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    for (i = 0; i < 11; i++) {
+        sysbus_init_irq(dev, &s->irqs[i]);
+    }
+    sysbus_init_irq(dev, &s->irqX);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_gpio_regs = {
+    .name = "strongarm-gpio",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ilevel, StrongARMGPIOInfo),
+        VMSTATE_UINT32(olevel, StrongARMGPIOInfo),
+        VMSTATE_UINT32(dir, StrongARMGPIOInfo),
+        VMSTATE_UINT32(rising, StrongARMGPIOInfo),
+        VMSTATE_UINT32(falling, StrongARMGPIOInfo),
+        VMSTATE_UINT32(status, StrongARMGPIOInfo),
+        VMSTATE_UINT32(gafr, StrongARMGPIOInfo),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_gpio_info = {
+    .init       = strongarm_gpio_initfn,
+    .qdev.name  = "strongarm-gpio",
+    .qdev.desc  = "StrongARM GPIO controller",
+    .qdev.size  = sizeof(StrongARMGPIOInfo),
+};
+
+/* Peripheral Pin Controller */
+#define PPDR 0x00
+#define PPSR 0x04
+#define PPAR 0x08
+#define PSDR 0x0c
+#define PPFR 0x10
+
+typedef struct StrongARMPPCInfo StrongARMPPCInfo;
+struct StrongARMPPCInfo {
+    SysBusDevice busdev;
+    qemu_irq handler[28];
+
+    uint32_t ilevel;
+    uint32_t olevel;
+    uint32_t dir;
+    uint32_t ppar;
+    uint32_t psdr;
+    uint32_t ppfr;
+
+    uint32_t prev_level;
+};
+
+static void strongarm_ppc_set(void *opaque, int line, int level)
+{
+    StrongARMPPCInfo *s = opaque;
+
+    if (level) {
+        s->ilevel |= 1 << line;
+    } else {
+        s->ilevel &= ~(1 << line);
+    }
+}
+
+static void strongarm_ppc_handler_update(StrongARMPPCInfo *s)
+{
+    uint32_t level, diff;
+    int bit;
+
+    level = s->olevel & s->dir;
+
+    for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+        bit = ffs(diff) - 1;
+        qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+    }
+
+    s->prev_level = level;
+}
+
+static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset)
+{
+    StrongARMPPCInfo *s = opaque;
+
+    switch (offset) {
+    case PPDR:        /* PPC Pin Direction registers */
+        return s->dir | ~0x3fffff;
+
+    case PPSR:        /* PPC Pin State registers */
+        return (s->olevel & s->dir) |
+               (s->ilevel & ~s->dir) |
+               ~0x3fffff;
+
+    case PPAR:
+        return s->ppar | ~0x41000;
+
+    case PSDR:
+        return s->psdr;
+
+    case PPFR:
+        return s->ppfr | ~0x7f001;
+
+    default:
+        printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+    }
+
+    return 0;
+}
+
+static void strongarm_ppc_write(void *opaque,
+                target_phys_addr_t offset, uint32_t value)
+{
+    StrongARMPPCInfo *s = opaque;
+
+    switch (offset) {
+    case PPDR:        /* PPC Pin Direction registers */
+        s->dir = value & 0x3fffff;
+        strongarm_ppc_handler_update(s);
+        break;
+
+    case PPSR:        /* PPC Pin State registers */
+        s->olevel = value & s->dir & 0x3fffff;
+        strongarm_ppc_handler_update(s);
+        break;
+
+    case PPAR:
+        s->ppar = value & 0x41000;
+        break;
+
+    case PSDR:
+        s->psdr = value & 0x3fffff;
+        break;
+
+    case PPFR:
+        s->ppfr = value & 0x7f001;
+        break;
+
+    default:
+        printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+    }
+}
+
+static CPUReadMemoryFunc * const strongarm_ppc_readfn[] = {
+    strongarm_ppc_read,
+    strongarm_ppc_read,
+    strongarm_ppc_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_ppc_writefn[] = {
+    strongarm_ppc_write,
+    strongarm_ppc_write,
+    strongarm_ppc_write
+};
+
+static int strongarm_ppc_init(SysBusDevice *dev)
+{
+    int iomemtype;
+    StrongARMPPCInfo *s;
+
+    s = FROM_SYSBUS(StrongARMPPCInfo, dev);
+
+    qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
+    qdev_init_gpio_out(&dev->qdev, s->handler, 22);
+
+    iomemtype = cpu_register_io_memory(strongarm_ppc_readfn,
+                    strongarm_ppc_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ppc_regs = {
+    .name = "strongarm-ppc",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ilevel, StrongARMPPCInfo),
+        VMSTATE_UINT32(olevel, StrongARMPPCInfo),
+        VMSTATE_UINT32(dir, StrongARMPPCInfo),
+        VMSTATE_UINT32(ppar, StrongARMPPCInfo),
+        VMSTATE_UINT32(psdr, StrongARMPPCInfo),
+        VMSTATE_UINT32(ppfr, StrongARMPPCInfo),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_ppc_info = {
+    .init       = strongarm_ppc_init,
+    .qdev.name  = "strongarm-ppc",
+    .qdev.desc  = "StrongARM PPC controller",
+    .qdev.size  = sizeof(StrongARMPPCInfo),
+};
+
+/* UART Ports */
+#define UTCR0 0x00
+#define UTCR1 0x04
+#define UTCR2 0x08
+#define UTCR3 0x0c
+#define UTDR  0x14
+#define UTSR0 0x1c
+#define UTSR1 0x20
+
+#define UTCR0_PE  (1 << 0) /* Parity enable */
+#define UTCR0_OES (1 << 1) /* Even parity */
+#define UTCR0_SBS (1 << 2) /* 2 stop bits */
+#define UTCR0_DSS (1 << 3) /* 8-bit data */
+
+#define UTCR3_RXE (1 << 0) /* Rx enable */
+#define UTCR3_TXE (1 << 1) /* Tx enable */
+#define UTCR3_BRK (1 << 2) /* Force Break */
+#define UTCR3_RIE (1 << 3) /* Rx int enable */
+#define UTCR3_TIE (1 << 4) /* Tx int enable */
+#define UTCR3_LBM (1 << 5) /* Loopback */
+
+#define UTSR0_TFS (1 << 0) /* Tx FIFO nearly empty */
+#define UTSR0_RFS (1 << 1) /* Rx FIFO nearly full */
+#define UTSR0_RID (1 << 2) /* Receiver Idle */
+#define UTSR0_RBB (1 << 3) /* Receiver begin break */
+#define UTSR0_REB (1 << 4) /* Receiver end break */
+#define UTSR0_EIF (1 << 5) /* Error in FIFO */
+
+#define UTSR1_RNE (1 << 1) /* Receive FIFO not empty */
+#define UTSR1_TNF (1 << 2) /* Transmit FIFO not full */
+#define UTSR1_PRE (1 << 3) /* Parity error */
+#define UTSR1_FRE (1 << 4) /* Frame error */
+#define UTSR1_ROR (1 << 5) /* Receive Over Run */
+
+#define RX_FIFO_PRE (1 << 8)
+#define RX_FIFO_FRE (1 << 9)
+#define RX_FIFO_ROR (1 << 10)
+
+typedef struct {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint8_t utcr0;
+    uint16_t brd;
+    uint8_t utcr3;
+    uint8_t utsr0;
+    uint8_t utsr1;
+
+    uint8_t tx_fifo[8];
+    uint8_t tx_start;
+    uint8_t tx_len;
+    uint16_t rx_fifo[12]; /* value + error flags in high bits */
+    uint8_t rx_start;
+    uint8_t rx_len;
+
+    uint64_t char_transmit_time; /* time to transmit a char in ticks*/
+    bool wait_break_end;
+    QEMUTimer *rx_timeout_timer;
+    QEMUTimer *tx_timer;
+} StrongARMUARTState;
+
+static void strongarm_uart_update_status(StrongARMUARTState *s)
+{
+    uint16_t utsr1 = 0;
+
+    if (s->tx_len != 8) {
+        utsr1 |= UTSR1_TNF;
+    }
+
+    if (s->rx_len != 0) {
+        uint16_t ent = s->rx_fifo[s->rx_start];
+
+        utsr1 |= UTSR1_RNE;
+        if (ent & RX_FIFO_PRE) {
+            s->utsr1 |= UTSR1_PRE;
+        }
+        if (ent & RX_FIFO_FRE) {
+            s->utsr1 |= UTSR1_FRE;
+        }
+        if (ent & RX_FIFO_ROR) {
+            s->utsr1 |= UTSR1_ROR;
+        }
+    }
+
+    s->utsr1 = utsr1;
+}
+
+static void strongarm_uart_update_int_status(StrongARMUARTState *s)
+{
+    uint16_t utsr0 = s->utsr0 &
+            (UTSR0_REB | UTSR0_RBB | UTSR0_RID);
+    int i;
+
+    if ((s->utcr3 & UTCR3_TXE) &&
+                (s->utcr3 & UTCR3_TIE) &&
+                s->tx_len <= 4) {
+        utsr0 |= UTSR0_TFS;
+    }
+
+    if ((s->utcr3 & UTCR3_RXE) &&
+                (s->utcr3 & UTCR3_RIE) &&
+                s->rx_len > 4) {
+        utsr0 |= UTSR0_RFS;
+    }
+
+    for (i = 0; i < s->rx_len && i < 4; i++)
+        if (s->rx_fifo[(s->rx_start + i) % 12] & ~0xff) {
+            utsr0 |= UTSR0_EIF;
+            break;
+        }
+
+    s->utsr0 = utsr0;
+    qemu_set_irq(s->irq, utsr0);
+}
+
+static void strongarm_uart_update_parameters(StrongARMUARTState *s)
+{
+    int speed, parity, data_bits, stop_bits, frame_size;
+    QEMUSerialSetParams ssp;
+
+    /* Start bit. */
+    frame_size = 1;
+    if (s->utcr0 & UTCR0_PE) {
+        /* Parity bit. */
+        frame_size++;
+        if (s->utcr0 & UTCR0_OES) {
+            parity = 'E';
+        } else {
+            parity = 'O';
+        }
+    } else {
+            parity = 'N';
+    }
+    if (s->utcr0 & UTCR0_SBS) {
+        stop_bits = 2;
+    } else {
+        stop_bits = 1;
+    }
+
+    data_bits = (s->utcr0 & UTCR0_DSS) ? 8 : 7;
+    frame_size += data_bits + stop_bits;
+    speed = 3686400 / 16 / (s->brd + 1);
+    ssp.speed = speed;
+    ssp.parity = parity;
+    ssp.data_bits = data_bits;
+    ssp.stop_bits = stop_bits;
+    s->char_transmit_time =  (get_ticks_per_sec() / speed) * frame_size;
+    if (s->chr) {
+        qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+    }
+
+    DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
+            speed, parity, data_bits, stop_bits);
+}
+
+static void strongarm_uart_rx_to(void *opaque)
+{
+    StrongARMUARTState *s = opaque;
+
+    if (s->rx_len) {
+        s->utsr0 |= UTSR0_RID;
+        strongarm_uart_update_int_status(s);
+    }
+}
+
+static void strongarm_uart_rx_push(StrongARMUARTState *s, uint16_t c)
+{
+    if ((s->utcr3 & UTCR3_RXE) == 0) {
+        /* rx disabled */
+        return;
+    }
+
+    if (s->wait_break_end) {
+        s->utsr0 |= UTSR0_REB;
+        s->wait_break_end = false;
+    }
+
+    if (s->rx_len < 12) {
+        s->rx_fifo[(s->rx_start + s->rx_len) % 12] = c;
+        s->rx_len++;
+    } else
+        s->rx_fifo[(s->rx_start + 11) % 12] |= RX_FIFO_ROR;
+}
+
+static int strongarm_uart_can_receive(void *opaque)
+{
+    StrongARMUARTState *s = opaque;
+
+    if (s->rx_len == 12) {
+        return 0;
+    }
+    /* It's best not to get more than 2/3 of RX FIFO, so advertise that much */
+    if (s->rx_len < 8) {
+        return 8 - s->rx_len;
+    }
+    return 1;
+}
+
+static void strongarm_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    StrongARMUARTState *s = opaque;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        strongarm_uart_rx_push(s, buf[i]);
+    }
+
+    /* call the timeout receive callback in 3 char transmit time */
+    qemu_mod_timer(s->rx_timeout_timer,
+                    qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+
+    strongarm_uart_update_status(s);
+    strongarm_uart_update_int_status(s);
+}
+
+static void strongarm_uart_event(void *opaque, int event)
+{
+    StrongARMUARTState *s = opaque;
+    if (event == CHR_EVENT_BREAK) {
+        s->utsr0 |= UTSR0_RBB;
+        strongarm_uart_rx_push(s, RX_FIFO_FRE);
+        s->wait_break_end = true;
+        strongarm_uart_update_status(s);
+        strongarm_uart_update_int_status(s);
+    }
+}
+
+static void strongarm_uart_tx(void *opaque)
+{
+    StrongARMUARTState *s = opaque;
+    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
+
+    if (s->utcr3 & UTCR3_LBM) /* loopback */ {
+        strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
+    } else if (s->chr) {
+        qemu_chr_write(s->chr, &s->tx_fifo[s->tx_start], 1);
+    }
+
+    s->tx_start = (s->tx_start + 1) % 8;
+    s->tx_len--;
+    if (s->tx_len) {
+        qemu_mod_timer(s->tx_timer, new_xmit_ts + s->char_transmit_time);
+    }
+    strongarm_uart_update_status(s);
+    strongarm_uart_update_int_status(s);
+}
+
+static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr)
+{
+    StrongARMUARTState *s = opaque;
+    uint16_t ret;
+
+    switch (addr) {
+    case UTCR0:
+        return s->utcr0;
+
+    case UTCR1:
+        return s->brd >> 8;
+
+    case UTCR2:
+        return s->brd & 0xff;
+
+    case UTCR3:
+        return s->utcr3;
+
+    case UTDR:
+        if (s->rx_len != 0) {
+            ret = s->rx_fifo[s->rx_start];
+            s->rx_start = (s->rx_start + 1) % 12;
+            s->rx_len--;
+            strongarm_uart_update_status(s);
+            strongarm_uart_update_int_status(s);
+            return ret;
+        }
+        return 0;
+
+    case UTSR0:
+        return s->utsr0;
+
+    case UTSR1:
+        return s->utsr1;
+
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+        return 0;
+    }
+}
+
+static void strongarm_uart_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    StrongARMUARTState *s = opaque;
+
+    switch (addr) {
+    case UTCR0:
+        s->utcr0 = value & 0x7f;
+        strongarm_uart_update_parameters(s);
+        break;
+
+    case UTCR1:
+        s->brd = (s->brd & 0xff) | ((value & 0xf) << 8);
+        strongarm_uart_update_parameters(s);
+        break;
+
+    case UTCR2:
+        s->brd = (s->brd & 0xf00) | (value & 0xff);
+        strongarm_uart_update_parameters(s);
+        break;
+
+    case UTCR3:
+        s->utcr3 = value & 0x3f;
+        if ((s->utcr3 & UTCR3_RXE) == 0) {
+            s->rx_len = 0;
+        }
+        if ((s->utcr3 & UTCR3_TXE) == 0) {
+            s->tx_len = 0;
+        }
+        strongarm_uart_update_status(s);
+        strongarm_uart_update_int_status(s);
+        break;
+
+    case UTDR:
+        if ((s->utcr3 & UTCR3_TXE) && s->tx_len != 8) {
+            s->tx_fifo[(s->tx_start + s->tx_len) % 8] = value;
+            s->tx_len++;
+            strongarm_uart_update_status(s);
+            strongarm_uart_update_int_status(s);
+            if (s->tx_len == 1) {
+                strongarm_uart_tx(s);
+            }
+        }
+        break;
+
+    case UTSR0:
+        s->utsr0 = s->utsr0 & ~(value &
+                (UTSR0_REB | UTSR0_RBB | UTSR0_RID));
+        strongarm_uart_update_int_status(s);
+        break;
+
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+    }
+}
+
+static CPUReadMemoryFunc * const strongarm_uart_readfn[] = {
+    strongarm_uart_read,
+    strongarm_uart_read,
+    strongarm_uart_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
+    strongarm_uart_write,
+    strongarm_uart_write,
+    strongarm_uart_write,
+};
+
+static int strongarm_uart_init(SysBusDevice *dev)
+{
+    StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+    int iomemtype;
+
+    iomemtype = cpu_register_io_memory(strongarm_uart_readfn,
+                    strongarm_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, 0x10000, iomemtype);
+    sysbus_init_irq(dev, &s->irq);
+
+    s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
+    s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr,
+                        strongarm_uart_can_receive,
+                        strongarm_uart_receive,
+                        strongarm_uart_event,
+                        s);
+    }
+
+    return 0;
+}
+
+static void strongarm_uart_reset(DeviceState *dev)
+{
+    StrongARMUARTState *s = DO_UPCAST(StrongARMUARTState, busdev.qdev, dev);
+
+    s->utcr0 = UTCR0_DSS; /* 8 data, no parity */
+    s->brd = 23;    /* 9600 */
+    /* enable send & recv - this actually violates spec */
+    s->utcr3 = UTCR3_TXE | UTCR3_RXE;
+
+    s->rx_len = s->tx_len = 0;
+
+    strongarm_uart_update_parameters(s);
+    strongarm_uart_update_status(s);
+    strongarm_uart_update_int_status(s);
+}
+
+static int strongarm_uart_post_load(void *opaque, int version_id)
+{
+    StrongARMUARTState *s = opaque;
+
+    strongarm_uart_update_parameters(s);
+    strongarm_uart_update_status(s);
+    strongarm_uart_update_int_status(s);
+
+    /* tx and restart timer */
+    if (s->tx_len) {
+        strongarm_uart_tx(s);
+    }
+
+    /* restart rx timeout timer */
+    if (s->rx_len) {
+        qemu_mod_timer(s->rx_timeout_timer,
+                qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_uart_regs = {
+    .name = "strongarm-uart",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = strongarm_uart_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(utcr0, StrongARMUARTState),
+        VMSTATE_UINT16(brd, StrongARMUARTState),
+        VMSTATE_UINT8(utcr3, StrongARMUARTState),
+        VMSTATE_UINT8(utsr0, StrongARMUARTState),
+        VMSTATE_UINT8_ARRAY(tx_fifo, StrongARMUARTState, 8),
+        VMSTATE_UINT8(tx_start, StrongARMUARTState),
+        VMSTATE_UINT8(tx_len, StrongARMUARTState),
+        VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMUARTState, 12),
+        VMSTATE_UINT8(rx_start, StrongARMUARTState),
+        VMSTATE_UINT8(rx_len, StrongARMUARTState),
+        VMSTATE_BOOL(wait_break_end, StrongARMUARTState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_uart_info = {
+    .init       = strongarm_uart_init,
+    .qdev.name  = "strongarm-uart",
+    .qdev.desc  = "StrongARM UART controller",
+    .qdev.size  = sizeof(StrongARMUARTState),
+    .qdev.reset = strongarm_uart_reset,
+    .qdev.vmsd  = &vmstate_strongarm_uart_regs,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+/* Synchronous Serial Ports */
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq irq;
+    SSIBus *bus;
+
+    uint16_t sscr[2];
+    uint16_t sssr;
+
+    uint16_t rx_fifo[8];
+    uint8_t rx_level;
+    uint8_t rx_start;
+} StrongARMSSPState;
+
+#define SSCR0 0x60 /* SSP Control register 0 */
+#define SSCR1 0x64 /* SSP Control register 1 */
+#define SSDR  0x6c /* SSP Data register */
+#define SSSR  0x74 /* SSP Status register */
+
+/* Bitfields for above registers */
+#define SSCR0_SPI(x)    (((x) & 0x30) == 0x00)
+#define SSCR0_SSP(x)    (((x) & 0x30) == 0x10)
+#define SSCR0_UWIRE(x)  (((x) & 0x30) == 0x20)
+#define SSCR0_PSP(x)    (((x) & 0x30) == 0x30)
+#define SSCR0_SSE       (1 << 7)
+#define SSCR0_DSS(x)    (((x) & 0xf) + 1)
+#define SSCR1_RIE       (1 << 0)
+#define SSCR1_TIE       (1 << 1)
+#define SSCR1_LBM       (1 << 2)
+#define SSSR_TNF        (1 << 2)
+#define SSSR_RNE        (1 << 3)
+#define SSSR_TFS        (1 << 5)
+#define SSSR_RFS        (1 << 6)
+#define SSSR_ROR        (1 << 7)
+#define SSSR_RW         0x0080
+
+static void strongarm_ssp_int_update(StrongARMSSPState *s)
+{
+    int level = 0;
+
+    level |= (s->sssr & SSSR_ROR);
+    level |= (s->sssr & SSSR_RFS)  &&  (s->sscr[1] & SSCR1_RIE);
+    level |= (s->sssr & SSSR_TFS)  &&  (s->sscr[1] & SSCR1_TIE);
+    qemu_set_irq(s->irq, level);
+}
+
+static void strongarm_ssp_fifo_update(StrongARMSSPState *s)
+{
+    s->sssr &= ~SSSR_TFS;
+    s->sssr &= ~SSSR_TNF;
+    if (s->sscr[0] & SSCR0_SSE) {
+        if (s->rx_level >= 4) {
+            s->sssr |= SSSR_RFS;
+        } else {
+            s->sssr &= ~SSSR_RFS;
+        }
+        if (s->rx_level) {
+            s->sssr |= SSSR_RNE;
+        } else {
+            s->sssr &= ~SSSR_RNE;
+        }
+        /* TX FIFO is never filled, so it is always in underrun
+           condition if SSP is enabled */
+        s->sssr |= SSSR_TFS;
+        s->sssr |= SSSR_TNF;
+    }
+
+    strongarm_ssp_int_update(s);
+}
+
+static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr)
+{
+    StrongARMSSPState *s = opaque;
+    uint32_t retval;
+
+    switch (addr) {
+    case SSCR0:
+        return s->sscr[0];
+    case SSCR1:
+        return s->sscr[1];
+    case SSSR:
+        return s->sssr;
+    case SSDR:
+        if (~s->sscr[0] & SSCR0_SSE) {
+            return 0xffffffff;
+        }
+        if (s->rx_level < 1) {
+            printf("%s: SSP Rx Underrun\n", __func__);
+            return 0xffffffff;
+        }
+        s->rx_level--;
+        retval = s->rx_fifo[s->rx_start++];
+        s->rx_start &= 0x7;
+        strongarm_ssp_fifo_update(s);
+        return retval;
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    StrongARMSSPState *s = opaque;
+
+    switch (addr) {
+    case SSCR0:
+        s->sscr[0] = value & 0xffbf;
+        if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) {
+            printf("%s: Wrong data size: %i bits\n", __func__,
+                            SSCR0_DSS(value));
+        }
+        if (!(value & SSCR0_SSE)) {
+            s->sssr = 0;
+            s->rx_level = 0;
+        }
+        strongarm_ssp_fifo_update(s);
+        break;
+
+    case SSCR1:
+        s->sscr[1] = value & 0x2f;
+        if (value & SSCR1_LBM) {
+            printf("%s: Attempt to use SSP LBM mode\n", __func__);
+        }
+        strongarm_ssp_fifo_update(s);
+        break;
+
+    case SSSR:
+        s->sssr &= ~(value & SSSR_RW);
+        strongarm_ssp_int_update(s);
+        break;
+
+    case SSDR:
+        if (SSCR0_UWIRE(s->sscr[0])) {
+            value &= 0xff;
+        } else
+            /* Note how 32bits overflow does no harm here */
+            value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
+
+        /* Data goes from here to the Tx FIFO and is shifted out from
+         * there directly to the slave, no need to buffer it.
+         */
+        if (s->sscr[0] & SSCR0_SSE) {
+            uint32_t readval;
+            if (s->sscr[1] & SSCR1_LBM) {
+                readval = value;
+            } else {
+                readval = ssi_transfer(s->bus, value);
+            }
+
+            if (s->rx_level < 0x08) {
+                s->rx_fifo[(s->rx_start + s->rx_level++) & 0x7] = readval;
+            } else {
+                s->sssr |= SSSR_ROR;
+            }
+        }
+        strongarm_ssp_fifo_update(s);
+        break;
+
+    default:
+        printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const strongarm_ssp_readfn[] = {
+    strongarm_ssp_read,
+    strongarm_ssp_read,
+    strongarm_ssp_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_ssp_writefn[] = {
+    strongarm_ssp_write,
+    strongarm_ssp_write,
+    strongarm_ssp_write,
+};
+
+static int strongarm_ssp_post_load(void *opaque, int version_id)
+{
+    StrongARMSSPState *s = opaque;
+
+    strongarm_ssp_fifo_update(s);
+
+    return 0;
+}
+
+static int strongarm_ssp_init(SysBusDevice *dev)
+{
+    int iomemtype;
+    StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    iomemtype = cpu_register_io_memory(strongarm_ssp_readfn,
+                                       strongarm_ssp_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+    s->bus = ssi_create_bus(&dev->qdev, "ssi");
+    return 0;
+}
+
+static void strongarm_ssp_reset(DeviceState *dev)
+{
+    StrongARMSSPState *s = DO_UPCAST(StrongARMSSPState, busdev.qdev, dev);
+    s->sssr = 0x03; /* 3 bit data, SPI, disabled */
+    s->rx_start = 0;
+    s->rx_level = 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ssp_regs = {
+    .name = "strongarm-ssp",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = strongarm_ssp_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2),
+        VMSTATE_UINT16(sssr, StrongARMSSPState),
+        VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMSSPState, 8),
+        VMSTATE_UINT8(rx_start, StrongARMSSPState),
+        VMSTATE_UINT8(rx_level, StrongARMSSPState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo strongarm_ssp_info = {
+    .init       = strongarm_ssp_init,
+    .qdev.name  = "strongarm-ssp",
+    .qdev.desc  = "StrongARM SSP controller",
+    .qdev.size  = sizeof(StrongARMSSPState),
+    .qdev.reset = strongarm_ssp_reset,
+    .qdev.vmsd  = &vmstate_strongarm_ssp_regs,
+};
+
+/* Main CPU functions */
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
+{
+    StrongARMState *s;
+    qemu_irq *pic;
+    int i;
+
+    s = qemu_mallocz(sizeof(StrongARMState));
+
+    if (!rev) {
+        rev = "sa1110-b5";
+    }
+
+    if (strncmp(rev, "sa1110", 6)) {
+        error_report("Machine requires a SA1110 processor.\n");
+        exit(1);
+    }
+
+    s->env = cpu_init(rev);
+
+    if (!s->env) {
+        error_report("Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    cpu_register_physical_memory(SA_SDCS0,
+                    sdram_size, qemu_ram_alloc(NULL, "strongarm.sdram",
+                                                sdram_size) | IO_MEM_RAM);
+
+    pic = arm_pic_init_cpu(s->env);
+    s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
+                    pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
+
+    sysbus_create_varargs("pxa25x-timer", 0x90000000,
+                    qdev_get_gpio_in(s->pic, SA_PIC_OSTC0),
+                    qdev_get_gpio_in(s->pic, SA_PIC_OSTC1),
+                    qdev_get_gpio_in(s->pic, SA_PIC_OSTC2),
+                    qdev_get_gpio_in(s->pic, SA_PIC_OSTC3),
+                    NULL);
+
+    sysbus_create_simple("strongarm-rtc", 0x90010000,
+                    qdev_get_gpio_in(s->pic, SA_PIC_RTC_ALARM));
+
+    s->gpio = strongarm_gpio_init(0x90040000, s->pic);
+
+    s->ppc = sysbus_create_varargs("strongarm-ppc", 0x90060000, NULL);
+
+    for (i = 0; sa_serial[i].io_base; i++) {
+        DeviceState *dev = qdev_create(NULL, "strongarm-uart");
+        qdev_prop_set_chr(dev, "chardev", serial_hds[i]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+                sa_serial[i].io_base);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+                qdev_get_gpio_in(s->pic, sa_serial[i].irq));
+    }
+
+    s->ssp = sysbus_create_varargs("strongarm-ssp", 0x80070000,
+                qdev_get_gpio_in(s->pic, SA_PIC_SSP), NULL);
+    s->ssp_bus = (SSIBus *)qdev_get_child_bus(s->ssp, "ssi");
+
+    return s;
+}
+
+static void strongarm_register_devices(void)
+{
+    sysbus_register_withprop(&strongarm_pic_info);
+    sysbus_register_withprop(&strongarm_rtc_sysbus_info);
+    sysbus_register_withprop(&strongarm_gpio_info);
+    sysbus_register_withprop(&strongarm_ppc_info);
+    sysbus_register_withprop(&strongarm_uart_info);
+    sysbus_register_withprop(&strongarm_ssp_info);
+}
+device_init(strongarm_register_devices)
diff --git a/hw/strongarm.h b/hw/strongarm.h
new file mode 100644
index 0000000..a81b110
--- /dev/null
+++ b/hw/strongarm.h
@@ -0,0 +1,64 @@
+#ifndef _STRONGARM_H
+#define _STRONGARM_H
+
+#define SA_CS0          0x00000000
+#define SA_CS1          0x08000000
+#define SA_CS2          0x10000000
+#define SA_CS3          0x18000000
+#define SA_PCMCIA_CS0   0x20000000
+#define SA_PCMCIA_CS1   0x30000000
+#define SA_CS4          0x40000000
+#define SA_CS5          0x48000000
+/* system registers here */
+#define SA_SDCS0        0xc0000000
+#define SA_SDCS1        0xc8000000
+#define SA_SDCS2        0xd0000000
+#define SA_SDCS3        0xd8000000
+
+enum {
+    SA_PIC_GPIO0_EDGE = 0,
+    SA_PIC_GPIO1_EDGE,
+    SA_PIC_GPIO2_EDGE,
+    SA_PIC_GPIO3_EDGE,
+    SA_PIC_GPIO4_EDGE,
+    SA_PIC_GPIO5_EDGE,
+    SA_PIC_GPIO6_EDGE,
+    SA_PIC_GPIO7_EDGE,
+    SA_PIC_GPIO8_EDGE,
+    SA_PIC_GPIO9_EDGE,
+    SA_PIC_GPIO10_EDGE,
+    SA_PIC_GPIOX_EDGE,
+    SA_PIC_LCD,
+    SA_PIC_UDC,
+    SA_PIC_RSVD1,
+    SA_PIC_UART1,
+    SA_PIC_UART2,
+    SA_PIC_UART3,
+    SA_PIC_MCP,
+    SA_PIC_SSP,
+    SA_PIC_DMA_CH0,
+    SA_PIC_DMA_CH1,
+    SA_PIC_DMA_CH2,
+    SA_PIC_DMA_CH3,
+    SA_PIC_DMA_CH4,
+    SA_PIC_DMA_CH5,
+    SA_PIC_OSTC0,
+    SA_PIC_OSTC1,
+    SA_PIC_OSTC2,
+    SA_PIC_OSTC3,
+    SA_PIC_RTC_HZ,
+    SA_PIC_RTC_ALARM,
+};
+
+typedef struct {
+    CPUState *env;
+    DeviceState *pic;
+    DeviceState *gpio;
+    DeviceState *ppc;
+    DeviceState *ssp;
+    SSIBus *ssp_bus;
+} StrongARMState;
+
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev);
+
+#endif
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e247a7a..d5af644 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -363,6 +363,7 @@ enum arm_features {
     ARM_FEATURE_V7MP,    /* v7 Multiprocessing Extensions */
     ARM_FEATURE_V4T,
     ARM_FEATURE_V5,
+    ARM_FEATURE_STRONGARM,
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -393,6 +394,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define ARM_CPUID_ARM946      0x41059461
 #define ARM_CPUID_TI915T      0x54029152
 #define ARM_CPUID_TI925T      0x54029252
+#define ARM_CPUID_SA1100      0x4401A11B
+#define ARM_CPUID_SA1110      0x6901B119
 #define ARM_CPUID_PXA250      0x69052100
 #define ARM_CPUID_PXA255      0x69052d00
 #define ARM_CPUID_PXA260      0x69052903
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 12127de..bf84335 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -214,6 +214,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0xd172172;
         env->cp15.c1_sys = 0x00000078;
         break;
+    case ARM_CPUID_SA1100:
+    case ARM_CPUID_SA1110:
+        set_feature(env, ARM_FEATURE_STRONGARM);
+        env->cp15.c1_sys = 0x00000070;
+        break;
     default:
         cpu_abort(env, "Bad CPU ID: %x\n", id);
         break;
@@ -378,6 +383,8 @@ static const struct arm_cpu_t arm_cpu_names[] = {
     { ARM_CPUID_CORTEXA9, "cortex-a9"},
     { ARM_CPUID_TI925T, "ti925t" },
     { ARM_CPUID_PXA250, "pxa250" },
+    { ARM_CPUID_SA1100,    "sa1100" },
+    { ARM_CPUID_SA1110,    "sa1110" },
     { ARM_CPUID_PXA255, "pxa255" },
     { ARM_CPUID_PXA260, "pxa260" },
     { ARM_CPUID_PXA261, "pxa261" },
@@ -1553,6 +1560,8 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
     case 9:
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             break;
+        if (arm_feature(env, ARM_FEATURE_STRONGARM))
+            break; /* Ignore ReadBuffer access */
         switch (crm) {
         case 0: /* Cache lockdown.  */
 	    switch (op1) {
commit 618ba8e6a1313df6a8366ac8ffee47e3f885ac90
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Apr 18 06:39:53 2011 +0000

    Remove unused function parameter from cpu_restore_state
    
    The previous patch removed the need for parameter puc.
    Is is now unused, so remove it.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index d57afef..395cd8c 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -808,7 +808,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     if (tb) {
         /* the PC is inside the translated code. It means that we have
            a virtual CPU fault */
-        cpu_restore_state(tb, env, pc, puc);
+        cpu_restore_state(tb, env, pc);
     }
 
     /* we restore the process signal mask as the sigreturn should
diff --git a/exec-all.h b/exec-all.h
index 29fd322..7c2d29f 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -84,8 +84,7 @@ void cpu_gen_init(void);
 int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 int cpu_restore_state(struct TranslationBlock *tb,
-                      CPUState *env, unsigned long searched_pc,
-                      void *puc);
+                      CPUState *env, unsigned long searched_pc);
 void cpu_resume_from_signal(CPUState *env1, void *puc);
 void cpu_io_recompile(CPUState *env, void *retaddr);
 TranslationBlock *tb_gen_code(CPUState *env, 
diff --git a/exec.c b/exec.c
index b1ee52a..c3dc68a 100644
--- a/exec.c
+++ b/exec.c
@@ -1070,8 +1070,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                 restore the CPU state */
 
                 current_tb_modified = 1;
-                cpu_restore_state(current_tb, env,
-                                  env->mem_io_pc, NULL);
+                cpu_restore_state(current_tb, env, env->mem_io_pc);
                 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
                                      &current_flags);
             }
@@ -1179,7 +1178,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
                    restore the CPU state */
 
             current_tb_modified = 1;
-            cpu_restore_state(current_tb, env, pc, puc);
+            cpu_restore_state(current_tb, env, pc);
             cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
                                  &current_flags);
         }
@@ -3266,7 +3265,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
                     cpu_abort(env, "check_watchpoint: could not find TB for "
                               "pc=%p", (void *)env->mem_io_pc);
                 }
-                cpu_restore_state(tb, env, env->mem_io_pc, NULL);
+                cpu_restore_state(tb, env, env->mem_io_pc);
                 tb_phys_invalidate(tb, -1);
                 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                     env->exception_index = EXCP_DEBUG;
@@ -4301,7 +4300,7 @@ void cpu_io_recompile(CPUState *env, void *retaddr)
                   retaddr);
     }
     n = env->icount_decr.u16.low + tb->icount;
-    cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
+    cpu_restore_state(tb, env, (unsigned long)retaddr);
     /* Calculate how many instructions had been executed before the fault
        occurred.  */
     n = n - env->icount_decr.u16.low;
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 9f71db4..4ccb10b 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1374,7 +1374,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         /* Exception index and error code are already set */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index ee7286b..8334fbc 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -90,7 +90,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         raise_exception(env->exception_index);
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index be9eb06..34329e2 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -77,7 +77,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
 
 		/* Evaluate flags after retranslation.  */
                 helper_top_evaluate_flags();
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index a73427f..fba536f 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4835,7 +4835,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index e84ba48..c72b1df 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -95,7 +95,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         cpu_loop_exit();
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 0711107..9b13bdb 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -68,7 +68,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         cpu_loop_exit();
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index b7cd6b2..c7b2f97 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -60,7 +60,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         cpu_loop_exit();
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8cba535..b8e4991 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -54,7 +54,7 @@ static void do_restore_state (void *pc_ptr)
     
     tb = tb_find_pc (pc);
     if (tb) {
-        cpu_restore_state (tb, env, pc, NULL);
+        cpu_restore_state(tb, env, pc);
     }
 }
 #endif
@@ -1972,7 +1972,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (tb) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 28d40ac..d5db484 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3741,7 +3741,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 402df2d..be455b9 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -61,7 +61,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
+                cpu_restore_state(tb, env, pc);
             }
         }
         /* XXX */
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index c127860..b909d18 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -32,7 +32,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
         if (tb) {
             /* the PC is inside the translated code. It means that we have
                a virtual CPU fault */
-            cpu_restore_state(tb, env, pc, NULL);
+            cpu_restore_state(tb, env, pc);
         }
     }
 }
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 854f168..ffffb8c 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -4375,7 +4375,7 @@ static void cpu_restore_state2(void *retaddr)
         if (tb) {
             /* the PC is inside the translated code. It means that we have
                a virtual CPU fault */
-            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
+            cpu_restore_state(tb, env, pc);
         }
     }
 }
diff --git a/translate-all.c b/translate-all.c
index 97668b2..2ca190c 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -112,8 +112,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
 /* The cpu state corresponding to 'searched_pc' is restored.
  */
 int cpu_restore_state(TranslationBlock *tb,
-                      CPUState *env, unsigned long searched_pc,
-                      void *puc)
+                      CPUState *env, unsigned long searched_pc)
 {
     TCGContext *s = &tcg_ctx;
     int j;
commit e87b7cb0f0e04d7c4510564530ab00ed4db37a45
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Apr 18 06:39:52 2011 +0000

    Remove unused function parameters from gen_pc_load and rename the function
    
    Function gen_pc_load was introduced in commit
    d2856f1ad4c259e5766847c49acbb4e390731bd4.
    The only reason for parameter searched_pc was
    a debug statement in target-i386/translate.c.
    
    Parameter puc was needed by target-sparc until
    commit d7da2a10402f1644128b66414ca8f86bdea9ae7c.
    
    Remove searched_pc from the debug statement and remove both
    parameters from the parameter list of gen_pc_load.
    
    As the function name gen_pc_load was also misleading,
    it is now called restore_state_to_opc. This new name
    was suggested by Peter Maydell, thanks.
    
    v2: Remove last parameter, too, and rename the function.
    
    v3: Fix [] typo in target-arm/translate.c.
        Fix wrong SHA1 object name in commit message (copy+paste error).
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>

diff --git a/exec-all.h b/exec-all.h
index 496c001..29fd322 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -77,8 +77,8 @@ extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
 
 void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
 void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
-                 unsigned long searched_pc, int pc_pos, void *puc);
+void restore_state_to_opc(CPUState *env, struct TranslationBlock *tb,
+                          int pc_pos);
 
 void cpu_gen_init(void);
 int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 96e922b..456ba51 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3367,8 +3367,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
     return env;
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
diff --git a/target-arm/translate.c b/target-arm/translate.c
index fc9ff8d..e1bda57 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9551,8 +9551,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
      * This is handled in the same way as restoration of the
      * PC in these situations: we will be called again with search_pc=1
      * and generate a mapping of the condexec bits for each PC in
-     * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
-     * the condexec bits.
+     * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
+     * this to restore the condexec bits.
      *
      * Note that there are no instructions which can read the condexec
      * bits, and none which can write non-static values to them, so
@@ -9817,8 +9817,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #endif
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->regs[15] = gen_opc_pc[pc_pos];
     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1c03fa5..e2607d6 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3604,8 +3604,7 @@ void cpu_reset (CPUCRISState *env)
 #endif
 }
 
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
-                 unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
 	env->pc = gen_opc_pc[pc_pos];
 }
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7d1340e..199302e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7890,8 +7890,7 @@ void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     int cc_op;
 #ifdef DEBUG_DISAS
@@ -7903,8 +7902,8 @@ void gen_pc_load(CPUState *env, TranslationBlock *tb,
                 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
             }
         }
-        qemu_log("spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
-                searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
+        qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
+                pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
                 (uint32_t)tb->cs_base);
     }
 #endif
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index efc9b5a..51b4f5a 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1212,8 +1212,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf(f, "\n\n");
 }
 
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
-                 unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 038c0af..9e5578d 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3113,8 +3113,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index bff3a11..b47b92e 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1940,8 +1940,7 @@ void cpu_reset (CPUState *env)
 #endif
 }
 
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
-                 unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 953c528..4eaa826 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12737,8 +12737,7 @@ void cpu_reset (CPUMIPSState *env)
     env->exception_index = EXCP_NONE;
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->active_tc.PC = gen_opc_pc[pc_pos];
     env->hflags &= ~MIPS_HFLAG_BMASK;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3c3ee24..a943dbc 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9367,8 +9367,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->nip = gen_opc_pc[pc_pos];
 }
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2cb893f..4d45e32 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -54,8 +54,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
 {
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->psw.addr = gen_opc_pc[pc_pos];
 }
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 88098d7..93c8636 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2069,8 +2069,7 @@ void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
     env->flags = gen_opc_hflags[pc_pos];
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 883ecd2..3c958b2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5080,8 +5080,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
     }
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-                unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     target_ulong npc;
     env->pc = gen_opc_pc[pc_pos];
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index a6ba991..98eaeb3 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2098,8 +2098,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #endif
 }
 
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
-        unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 {
     env->regs[31] = gen_opc_pc[pc_pos];
 }
diff --git a/translate-all.c b/translate-all.c
index efcfb9a..97668b2 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -157,7 +157,7 @@ int cpu_restore_state(TranslationBlock *tb,
         j--;
     env->icount_decr.u16.low -= gen_opc_icount[j];
 
-    gen_pc_load(env, tb, searched_pc, j, puc);
+    restore_state_to_opc(env, tb, j);
 
 #ifdef CONFIG_PROFILER
     s->restore_time += profile_getclock() - ti;
commit 8d5192ee15bc519f83741f5e413ebba5d57a6abd
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 15 17:32:50 2011 +0200

    s390x: virtio machine storage keys
    
    For emulation (and migration) we need to know about the guest's storage keys.
    These are separate from actual RAM contents, so we need to allocate them in
    parallel to RAM.
    
    While touching the file, this patch also adjusts the hypercall function
    to a new syntax that aligns better with tcg emulated code.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 48fb0d0..698ff6f 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -82,13 +82,12 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
     return ipi_states[cpu_addr];
 }
 
-int s390_virtio_hypercall(CPUState *env, uint64_t mem_, uint64_t hypercall)
+int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
 {
     int r = 0, i;
-    target_ulong mem = env->regs[2];
 
-    dprintf("KVM hypercall: %ld\n", env->regs[1]);
-    switch (env->regs[1]) {
+    dprintf("KVM hypercall: %ld\n", hypercall);
+    switch (hypercall) {
     case KVM_S390_VIRTIO_NOTIFY:
         if (mem > ram_size) {
             VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus,
@@ -128,8 +127,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem_, uint64_t hypercall)
         break;
     }
 
-    env->regs[2] = r;
-    return 0;
+    return r;
 }
 
 /* PC hardware initialisation */
@@ -145,14 +143,9 @@ static void s390_init(ram_addr_t ram_size,
     ram_addr_t kernel_size = 0;
     ram_addr_t initrd_offset;
     ram_addr_t initrd_size = 0;
+    uint8_t *storage_keys;
     int i;
 
-    /* XXX we only work on KVM for now */
-
-    if (!kvm_enabled()) {
-        fprintf(stderr, "The S390 target only works with KVM enabled\n");
-        exit(1);
-    }
 
     /* get a BUS */
     s390_bus = s390_virtio_bus_init(&ram_size);
@@ -161,6 +154,9 @@ static void s390_init(ram_addr_t ram_size,
     ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_addr);
 
+    /* allocate storage keys */
+    storage_keys = qemu_mallocz(ram_size / TARGET_PAGE_SIZE);
+
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = "host";
@@ -178,6 +174,7 @@ static void s390_init(ram_addr_t ram_size,
         ipi_states[i] = tmp_env;
         tmp_env->halted = 1;
         tmp_env->exception_index = EXCP_HLT;
+        tmp_env->storage_keys = storage_keys;
     }
 
     env->halted = 0;
commit 8103b4d161d7c00ea3ff89ffe66bb2bc2c67de5d
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 15 17:32:49 2011 +0200

    s390x: Dispatch interrupts to KVM or the real CPU
    
    The KVM interrupt injection path is non-generic for now. So we need to push
    knowledge of how to inject a device interrupt using KVM into the actual device
    code.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 175e5cb..bb49e39 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -43,6 +43,8 @@
     do { } while (0)
 #endif
 
+#define VIRTIO_EXT_CODE   0x2603
+
 struct BusInfo s390_virtio_bus_info = {
     .name       = "s390-virtio",
     .size       = sizeof(VirtIOS390Bus),
@@ -305,9 +307,13 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
 {
     VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
     uint64_t token = s390_virtio_device_vq_token(dev, vector);
+    CPUState *env = s390_cpu_addr2state(0);
 
-    /* XXX kvm dependency! */
-    kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
+    if (kvm_enabled()) {
+        kvm_s390_virtio_irq(env, 0, token);
+    } else {
+        cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token);
+    }
 }
 
 static unsigned virtio_s390_get_features(void *opaque)
commit 3110e2925489c571901e945e315942ce84fe696f
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 15 17:32:48 2011 +0200

    s390x: Enable s390x-softmmu target
    
    This patch adds some code paths for running s390x guest OSs without the
    need for KVM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-exec.c b/cpu-exec.c
index 5d6c9a8..d57afef 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -346,6 +346,8 @@ int cpu_exec(CPUState *env1)
                     do_interrupt(env);
 #elif defined(TARGET_M68K)
                     do_interrupt(0);
+#elif defined(TARGET_S390X)
+                    do_interrupt(env);
 #endif
                     env->exception_index = -1;
 #endif
@@ -560,6 +562,12 @@ int cpu_exec(CPUState *env1)
                         do_interrupt(1);
                         next_tb = 0;
                     }
+#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
+                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                        (env->psw.mask & PSW_MASK_EXT)) {
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #endif
                    /* Don't use the cached interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
index f7893f3..7a87fff 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -31,7 +31,16 @@ register struct CPUS390XState *env asm(AREG0);
 
 static inline int cpu_has_work(CPUState *env)
 {
-    return env->interrupt_request & CPU_INTERRUPT_HARD; // guess
+    return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (env->psw.mask & PSW_MASK_EXT));
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+static inline void env_to_regs(void)
+{
 }
 
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 4a5297b..629dfd9 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -82,3 +82,7 @@ int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     return 0;
 }
 #endif /* CONFIG_USER_ONLY */
+
+void do_interrupt (CPUState *env)
+{
+}
commit bcec36eaa0f8570d455214512f1d6382410c509e
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 15 17:32:47 2011 +0200

    s390x: Prepare cpu.h for emulation
    
    We need to add some more logic to the CPU description to leverage emulation
    of an s390x CPU. This patch adds all the required helpers, fields in CPUState
    and constant definitions required for user and system emulation.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index d429f10..48fb0d0 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -82,7 +82,7 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
     return ipi_states[cpu_addr];
 }
 
-int s390_virtio_hypercall(CPUState *env)
+int s390_virtio_hypercall(CPUState *env, uint64_t mem_, uint64_t hypercall)
 {
     int r = 0, i;
     target_ulong mem = env->regs[2];
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e47c372..a84b3ee 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -26,24 +26,35 @@
 #define CPUState struct CPUS390XState
 
 #include "cpu-defs.h"
+#define TARGET_PAGE_BITS 12
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 64
+#define TARGET_VIRT_ADDR_SPACE_BITS 64
+
+#include "cpu-all.h"
 
 #include "softfloat.h"
 
-#define NB_MMU_MODES 2
+#define NB_MMU_MODES 3
 
-typedef union FPReg {
-    struct {
-#ifdef WORDS_BIGENDIAN
-        float32 e;
-        int32_t __pad;
-#else
-        int32_t __pad;
-        float32 e;
-#endif
-    };
-    float64 d;
-    uint64_t i;
-} FPReg;
+#define MMU_MODE0_SUFFIX _primary
+#define MMU_MODE1_SUFFIX _secondary
+#define MMU_MODE2_SUFFIX _home
+
+#define MMU_USER_IDX 1
+
+#define MAX_EXT_QUEUE 16
+
+typedef struct PSW {
+    uint64_t mask;
+    uint64_t addr;
+} PSW;
+
+typedef struct ExtQueue {
+    uint32_t code;
+    uint32_t param;
+    uint32_t param64;
+} ExtQueue;
 
 typedef struct CPUS390XState {
     uint64_t regs[16];	/* GP registers */
@@ -51,17 +62,42 @@ typedef struct CPUS390XState {
     uint32_t aregs[16];	/* access registers */
 
     uint32_t fpc;	/* floating-point control register */
-    FPReg fregs[16]; /* FP registers */
+    CPU_DoubleU fregs[16]; /* FP registers */
     float_status fpu_status; /* passed to softfloat lib */
 
-    struct {
-        uint64_t mask;
-        uint64_t addr;
-    } psw;
+    PSW psw;
 
-    int cc; /* condition code (0-3) */
+    uint32_t cc;
+    uint32_t cc_op;
+    uint64_t cc_src;
+    uint64_t cc_dst;
+    uint64_t cc_vr;
 
     uint64_t __excp_addr;
+    uint64_t psa;
+
+    uint32_t int_pgm_code;
+    uint32_t int_pgm_ilc;
+
+    uint32_t int_svc_code;
+    uint32_t int_svc_ilc;
+
+    uint64_t cregs[16]; /* control registers */
+
+    int pending_int;
+    ExtQueue ext_queue[MAX_EXT_QUEUE];
+
+    /* reset does memset(0) up to here */
+
+    int ext_index;
+    int cpu_num;
+    uint8_t *storage_keys;
+
+    uint64_t tod_offset;
+    uint64_t tod_basetime;
+    QEMUTimer *tod_timer;
+
+    QEMUTimer *cpu_timer;
 
     CPU_COMMON
 } CPUS390XState;
@@ -69,24 +105,174 @@ typedef struct CPUS390XState {
 #if defined(CONFIG_USER_ONLY)
 static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 {
-    if (newsp)
+    if (newsp) {
         env->regs[15] = newsp;
+    }
     env->regs[0] = 0;
 }
 #endif
 
-#define MMU_MODE0_SUFFIX _kernel
-#define MMU_MODE1_SUFFIX _user
-#define MMU_USER_IDX 1
+/* Interrupt Codes */
+/* Program Interrupts */
+#define PGM_OPERATION                   0x0001
+#define PGM_PRIVILEGED                  0x0002
+#define PGM_EXECUTE                     0x0003
+#define PGM_PROTECTION                  0x0004
+#define PGM_ADDRESSING                  0x0005
+#define PGM_SPECIFICATION               0x0006
+#define PGM_DATA                        0x0007
+#define PGM_FIXPT_OVERFLOW              0x0008
+#define PGM_FIXPT_DIVIDE                0x0009
+#define PGM_DEC_OVERFLOW                0x000a
+#define PGM_DEC_DIVIDE                  0x000b
+#define PGM_HFP_EXP_OVERFLOW            0x000c
+#define PGM_HFP_EXP_UNDERFLOW           0x000d
+#define PGM_HFP_SIGNIFICANCE            0x000e
+#define PGM_HFP_DIVIDE                  0x000f
+#define PGM_SEGMENT_TRANS               0x0010
+#define PGM_PAGE_TRANS                  0x0011
+#define PGM_TRANS_SPEC                  0x0012
+#define PGM_SPECIAL_OP                  0x0013
+#define PGM_OPERAND                     0x0015
+#define PGM_TRACE_TABLE                 0x0016
+#define PGM_SPACE_SWITCH                0x001c
+#define PGM_HFP_SQRT                    0x001d
+#define PGM_PC_TRANS_SPEC               0x001f
+#define PGM_AFX_TRANS                   0x0020
+#define PGM_ASX_TRANS                   0x0021
+#define PGM_LX_TRANS                    0x0022
+#define PGM_EX_TRANS                    0x0023
+#define PGM_PRIM_AUTH                   0x0024
+#define PGM_SEC_AUTH                    0x0025
+#define PGM_ALET_SPEC                   0x0028
+#define PGM_ALEN_SPEC                   0x0029
+#define PGM_ALE_SEQ                     0x002a
+#define PGM_ASTE_VALID                  0x002b
+#define PGM_ASTE_SEQ                    0x002c
+#define PGM_EXT_AUTH                    0x002d
+#define PGM_STACK_FULL                  0x0030
+#define PGM_STACK_EMPTY                 0x0031
+#define PGM_STACK_SPEC                  0x0032
+#define PGM_STACK_TYPE                  0x0033
+#define PGM_STACK_OP                    0x0034
+#define PGM_ASCE_TYPE                   0x0038
+#define PGM_REG_FIRST_TRANS             0x0039
+#define PGM_REG_SEC_TRANS               0x003a
+#define PGM_REG_THIRD_TRANS             0x003b
+#define PGM_MONITOR                     0x0040
+#define PGM_PER                         0x0080
+#define PGM_CRYPTO                      0x0119
+
+/* External Interrupts */
+#define EXT_INTERRUPT_KEY               0x0040
+#define EXT_CLOCK_COMP                  0x1004
+#define EXT_CPU_TIMER                   0x1005
+#define EXT_MALFUNCTION                 0x1200
+#define EXT_EMERGENCY                   0x1201
+#define EXT_EXTERNAL_CALL               0x1202
+#define EXT_ETR                         0x1406
+#define EXT_SERVICE                     0x2401
+#define EXT_VIRTIO                      0x2603
+
+/* PSW defines */
+#undef PSW_MASK_PER
+#undef PSW_MASK_DAT
+#undef PSW_MASK_IO
+#undef PSW_MASK_EXT
+#undef PSW_MASK_KEY
+#undef PSW_SHIFT_KEY
+#undef PSW_MASK_MCHECK
+#undef PSW_MASK_WAIT
+#undef PSW_MASK_PSTATE
+#undef PSW_MASK_ASC
+#undef PSW_MASK_CC
+#undef PSW_MASK_PM
+#undef PSW_MASK_64
+
+#define PSW_MASK_PER            0x4000000000000000ULL
+#define PSW_MASK_DAT            0x0400000000000000ULL
+#define PSW_MASK_IO             0x0200000000000000ULL
+#define PSW_MASK_EXT            0x0100000000000000ULL
+#define PSW_MASK_KEY            0x00F0000000000000ULL
+#define PSW_SHIFT_KEY           56
+#define PSW_MASK_MCHECK         0x0004000000000000ULL
+#define PSW_MASK_WAIT           0x0002000000000000ULL
+#define PSW_MASK_PSTATE         0x0001000000000000ULL
+#define PSW_MASK_ASC            0x0000C00000000000ULL
+#define PSW_MASK_CC             0x0000300000000000ULL
+#define PSW_MASK_PM             0x00000F0000000000ULL
+#define PSW_MASK_64             0x0000000100000000ULL
+#define PSW_MASK_32             0x0000000080000000ULL
+
+#undef PSW_ASC_PRIMARY
+#undef PSW_ASC_ACCREG
+#undef PSW_ASC_SECONDARY
+#undef PSW_ASC_HOME
+
+#define PSW_ASC_PRIMARY         0x0000000000000000ULL
+#define PSW_ASC_ACCREG          0x0000400000000000ULL
+#define PSW_ASC_SECONDARY       0x0000800000000000ULL
+#define PSW_ASC_HOME            0x0000C00000000000ULL
+
+/* tb flags */
+
+#define FLAG_MASK_PER           (PSW_MASK_PER    >> 32)
+#define FLAG_MASK_DAT           (PSW_MASK_DAT    >> 32)
+#define FLAG_MASK_IO            (PSW_MASK_IO     >> 32)
+#define FLAG_MASK_EXT           (PSW_MASK_EXT    >> 32)
+#define FLAG_MASK_KEY           (PSW_MASK_KEY    >> 32)
+#define FLAG_MASK_MCHECK        (PSW_MASK_MCHECK >> 32)
+#define FLAG_MASK_WAIT          (PSW_MASK_WAIT   >> 32)
+#define FLAG_MASK_PSTATE        (PSW_MASK_PSTATE >> 32)
+#define FLAG_MASK_ASC           (PSW_MASK_ASC    >> 32)
+#define FLAG_MASK_CC            (PSW_MASK_CC     >> 32)
+#define FLAG_MASK_PM            (PSW_MASK_PM     >> 32)
+#define FLAG_MASK_64            (PSW_MASK_64     >> 32)
+#define FLAG_MASK_32            0x00001000
+
 static inline int cpu_mmu_index (CPUState *env)
 {
-    /* XXX: Currently we don't implement virtual memory */
+    if (env->psw.mask & PSW_MASK_PSTATE) {
+        return 1;
+    }
+
     return 0;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->psw.addr;
+    *cs_base = 0;
+    *flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) |
+             ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
+}
+
+static inline int get_ilc(uint8_t opc)
+{
+    switch (opc >> 6) {
+    case 0:
+        return 1;
+    case 1:
+    case 2:
+        return 2;
+    case 3:
+        return 3;
+    }
+
+    return 0;
+}
+
+#define ILC_LATER       0x20
+#define ILC_LATER_INC   0x21
+#define ILC_LATER_INC_2 0x22
+
+
 CPUS390XState *cpu_s390x_init(const char *cpu_model);
+void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
 void cpu_s390x_close(CPUS390XState *s);
+void do_interrupt (CPUState *env);
 
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
@@ -97,41 +283,61 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
                               int mmu_idx, int is_softmuu);
 #define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault
 
-#define TARGET_PAGE_BITS 12
-
-/* ??? This is certainly wrong for 64-bit s390x, but given that only KVM
-   emulation actually works, this is good enough for a placeholder.  */
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
 
 #ifndef CONFIG_USER_ONLY
-int s390_virtio_hypercall(CPUState *env);
+int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall);
+
+void kvm_s390_interrupt(CPUState *env, int type, uint32_t code);
 void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
+void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+                                 uint64_t parm64, int vm);
 CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+
+#ifndef KVM_S390_SIGP_STOP
+#define KVM_S390_SIGP_STOP              0
+#define KVM_S390_PROGRAM_INT            0
+#define KVM_S390_SIGP_SET_PREFIX        0
+#define KVM_S390_RESTART                0
+#define KVM_S390_INT_VIRTIO             0
+#define KVM_S390_INT_SERVICE            0
+#define KVM_S390_INT_EMERGENCY          0
+#endif
+
 #endif
+void cpu_lock(void);
+void cpu_unlock(void);
 
+static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
+{
+    env->aregs[0] = newtls >> 32;
+    env->aregs[1] = newtls & 0xffffffffULL;
+}
 
 #define cpu_init cpu_s390x_init
 #define cpu_exec cpu_s390x_exec
 #define cpu_gen_code cpu_s390x_gen_code
+#define cpu_signal_handler cpu_s390x_signal_handler
 
-#include "cpu-all.h"
+#include "exec-all.h"
+
+#ifdef CONFIG_USER_ONLY
 
 #define EXCP_OPEX 1 /* operation exception (sigill) */
 #define EXCP_SVC 2 /* supervisor call (syscall) */
 #define EXCP_ADDR 5 /* addressing exception */
-#define EXCP_EXECUTE_SVC 0xff00000 /* supervisor call via execute insn */
+#define EXCP_SPEC 6 /* specification exception */
 
-static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
-                                        target_ulong *cs_base, int *flags)
-{
-    *pc = env->psw.addr;
-    /* XXX this is correct for user-mode emulation, but needs
-     *     the asce register information as well when softmmu
-     *     is implemented in the future */
-    *cs_base = 0;
-    *flags = env->psw.mask;
-}
+#else
+
+#define EXCP_EXT 1 /* external interrupt */
+#define EXCP_SVC 2 /* supervisor call (syscall) */
+#define EXCP_PGM 3 /* program interruption */
+
+#endif /* CONFIG_USER_ONLY */
+
+#define INTERRUPT_EXT        (1 << 0)
+#define INTERRUPT_TOD        (1 << 1)
+#define INTERRUPT_CPUTIMER   (1 << 2)
 
 /* Program Status Word.  */
 #define S390_PSWM_REGNUM 0
@@ -265,5 +471,485 @@ static inline void cpu_get_tb_cpu_state(CPUState* env, target_ulong *pc,
 #define S390_NUM_PSEUDO_REGS 2
 #define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
 
+/* CC optimization */
+
+enum cc_op {
+    CC_OP_CONST0 = 0,           /* CC is 0 */
+    CC_OP_CONST1,               /* CC is 1 */
+    CC_OP_CONST2,               /* CC is 2 */
+    CC_OP_CONST3,               /* CC is 3 */
+
+    CC_OP_DYNAMIC,              /* CC calculation defined by env->cc_op */
+    CC_OP_STATIC,               /* CC value is env->cc_op */
+
+    CC_OP_NZ,                   /* env->cc_dst != 0 */
+    CC_OP_LTGT_32,              /* signed less/greater than (32bit) */
+    CC_OP_LTGT_64,              /* signed less/greater than (64bit) */
+    CC_OP_LTUGTU_32,            /* unsigned less/greater than (32bit) */
+    CC_OP_LTUGTU_64,            /* unsigned less/greater than (64bit) */
+    CC_OP_LTGT0_32,             /* signed less/greater than 0 (32bit) */
+    CC_OP_LTGT0_64,             /* signed less/greater than 0 (64bit) */
+
+    CC_OP_ADD_64,               /* overflow on add (64bit) */
+    CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
+    CC_OP_SUB_64,               /* overflow on substraction (64bit) */
+    CC_OP_SUBU_64,              /* overflow on unsigned substraction (64bit) */
+    CC_OP_ABS_64,               /* sign eval on abs (64bit) */
+    CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
+
+    CC_OP_ADD_32,               /* overflow on add (32bit) */
+    CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
+    CC_OP_SUB_32,               /* overflow on substraction (32bit) */
+    CC_OP_SUBU_32,              /* overflow on unsigned substraction (32bit) */
+    CC_OP_ABS_32,               /* sign eval on abs (64bit) */
+    CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
+
+    CC_OP_COMP_32,              /* complement */
+    CC_OP_COMP_64,              /* complement */
+
+    CC_OP_TM_32,                /* test under mask (32bit) */
+    CC_OP_TM_64,                /* test under mask (64bit) */
+
+    CC_OP_LTGT_F32,             /* FP compare (32bit) */
+    CC_OP_LTGT_F64,             /* FP compare (64bit) */
+
+    CC_OP_NZ_F32,               /* FP dst != 0 (32bit) */
+    CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
+
+    CC_OP_ICM,                  /* insert characters under mask */
+    CC_OP_SLAG,                 /* Calculate shift left signed */
+    CC_OP_MAX
+};
+
+static const char *cc_names[] = {
+    [CC_OP_CONST0]    = "CC_OP_CONST0",
+    [CC_OP_CONST1]    = "CC_OP_CONST1",
+    [CC_OP_CONST2]    = "CC_OP_CONST2",
+    [CC_OP_CONST3]    = "CC_OP_CONST3",
+    [CC_OP_DYNAMIC]   = "CC_OP_DYNAMIC",
+    [CC_OP_STATIC]    = "CC_OP_STATIC",
+    [CC_OP_NZ]        = "CC_OP_NZ",
+    [CC_OP_LTGT_32]   = "CC_OP_LTGT_32",
+    [CC_OP_LTGT_64]   = "CC_OP_LTGT_64",
+    [CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
+    [CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
+    [CC_OP_LTGT0_32]  = "CC_OP_LTGT0_32",
+    [CC_OP_LTGT0_64]  = "CC_OP_LTGT0_64",
+    [CC_OP_ADD_64]    = "CC_OP_ADD_64",
+    [CC_OP_ADDU_64]   = "CC_OP_ADDU_64",
+    [CC_OP_SUB_64]    = "CC_OP_SUB_64",
+    [CC_OP_SUBU_64]   = "CC_OP_SUBU_64",
+    [CC_OP_ABS_64]    = "CC_OP_ABS_64",
+    [CC_OP_NABS_64]   = "CC_OP_NABS_64",
+    [CC_OP_ADD_32]    = "CC_OP_ADD_32",
+    [CC_OP_ADDU_32]   = "CC_OP_ADDU_32",
+    [CC_OP_SUB_32]    = "CC_OP_SUB_32",
+    [CC_OP_SUBU_32]   = "CC_OP_SUBU_32",
+    [CC_OP_ABS_32]    = "CC_OP_ABS_32",
+    [CC_OP_NABS_32]   = "CC_OP_NABS_32",
+    [CC_OP_COMP_32]   = "CC_OP_COMP_32",
+    [CC_OP_COMP_64]   = "CC_OP_COMP_64",
+    [CC_OP_TM_32]     = "CC_OP_TM_32",
+    [CC_OP_TM_64]     = "CC_OP_TM_64",
+    [CC_OP_LTGT_F32]  = "CC_OP_LTGT_F32",
+    [CC_OP_LTGT_F64]  = "CC_OP_LTGT_F64",
+    [CC_OP_NZ_F32]    = "CC_OP_NZ_F32",
+    [CC_OP_NZ_F64]    = "CC_OP_NZ_F64",
+    [CC_OP_ICM]       = "CC_OP_ICM",
+    [CC_OP_SLAG]      = "CC_OP_SLAG",
+};
+
+static inline const char *cc_name(int cc_op)
+{
+    return cc_names[cc_op];
+}
+
+/* SCLP PV interface defines */
+#define SCLP_CMDW_READ_SCP_INFO         0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
+
+#define SCP_LENGTH                      0x00
+#define SCP_FUNCTION_CODE               0x02
+#define SCP_CONTROL_MASK                0x03
+#define SCP_RESPONSE_CODE               0x06
+#define SCP_MEM_CODE                    0x08
+#define SCP_INCREMENT                   0x0a
+
+typedef struct LowCore
+{
+    /* prefix area: defined by architecture */
+    uint32_t        ccw1[2];                  /* 0x000 */
+    uint32_t        ccw2[4];                  /* 0x008 */
+    uint8_t         pad1[0x80-0x18];          /* 0x018 */
+    uint32_t        ext_params;               /* 0x080 */
+    uint16_t        cpu_addr;                 /* 0x084 */
+    uint16_t        ext_int_code;             /* 0x086 */
+    uint16_t        svc_ilc;                  /* 0x088 */
+    uint16_t        svc_code;                 /* 0x08a */
+    uint16_t        pgm_ilc;                  /* 0x08c */
+    uint16_t        pgm_code;                 /* 0x08e */
+    uint32_t        data_exc_code;            /* 0x090 */
+    uint16_t        mon_class_num;            /* 0x094 */
+    uint16_t        per_perc_atmid;           /* 0x096 */
+    uint64_t        per_address;              /* 0x098 */
+    uint8_t         exc_access_id;            /* 0x0a0 */
+    uint8_t         per_access_id;            /* 0x0a1 */
+    uint8_t         op_access_id;             /* 0x0a2 */
+    uint8_t         ar_access_id;             /* 0x0a3 */
+    uint8_t         pad2[0xA8-0xA4];          /* 0x0a4 */
+    uint64_t        trans_exc_code;           /* 0x0a8 */
+    uint64_t        monitor_code;             /* 0x0b0 */
+    uint16_t        subchannel_id;            /* 0x0b8 */
+    uint16_t        subchannel_nr;            /* 0x0ba */
+    uint32_t        io_int_parm;              /* 0x0bc */
+    uint32_t        io_int_word;              /* 0x0c0 */
+    uint8_t         pad3[0xc8-0xc4];          /* 0x0c4 */
+    uint32_t        stfl_fac_list;            /* 0x0c8 */
+    uint8_t         pad4[0xe8-0xcc];          /* 0x0cc */
+    uint32_t        mcck_interruption_code[2]; /* 0x0e8 */
+    uint8_t         pad5[0xf4-0xf0];          /* 0x0f0 */
+    uint32_t        external_damage_code;     /* 0x0f4 */
+    uint64_t        failing_storage_address;  /* 0x0f8 */
+    uint8_t         pad6[0x120-0x100];        /* 0x100 */
+    PSW             restart_old_psw;          /* 0x120 */
+    PSW             external_old_psw;         /* 0x130 */
+    PSW             svc_old_psw;              /* 0x140 */
+    PSW             program_old_psw;          /* 0x150 */
+    PSW             mcck_old_psw;             /* 0x160 */
+    PSW             io_old_psw;               /* 0x170 */
+    uint8_t         pad7[0x1a0-0x180];        /* 0x180 */
+    PSW             restart_psw;              /* 0x1a0 */
+    PSW             external_new_psw;         /* 0x1b0 */
+    PSW             svc_new_psw;              /* 0x1c0 */
+    PSW             program_new_psw;          /* 0x1d0 */
+    PSW             mcck_new_psw;             /* 0x1e0 */
+    PSW             io_new_psw;               /* 0x1f0 */
+    PSW             return_psw;               /* 0x200 */
+    uint8_t         irb[64];                  /* 0x210 */
+    uint64_t        sync_enter_timer;         /* 0x250 */
+    uint64_t        async_enter_timer;        /* 0x258 */
+    uint64_t        exit_timer;               /* 0x260 */
+    uint64_t        last_update_timer;        /* 0x268 */
+    uint64_t        user_timer;               /* 0x270 */
+    uint64_t        system_timer;             /* 0x278 */
+    uint64_t        last_update_clock;        /* 0x280 */
+    uint64_t        steal_clock;              /* 0x288 */
+    PSW             return_mcck_psw;          /* 0x290 */
+    uint8_t         pad8[0xc00-0x2a0];        /* 0x2a0 */
+    /* System info area */
+    uint64_t        save_area[16];            /* 0xc00 */
+    uint8_t         pad9[0xd40-0xc80];        /* 0xc80 */
+    uint64_t        kernel_stack;             /* 0xd40 */
+    uint64_t        thread_info;              /* 0xd48 */
+    uint64_t        async_stack;              /* 0xd50 */
+    uint64_t        kernel_asce;              /* 0xd58 */
+    uint64_t        user_asce;                /* 0xd60 */
+    uint64_t        panic_stack;              /* 0xd68 */
+    uint64_t        user_exec_asce;           /* 0xd70 */
+    uint8_t         pad10[0xdc0-0xd78];       /* 0xd78 */
+
+    /* SMP info area: defined by DJB */
+    uint64_t        clock_comparator;         /* 0xdc0 */
+    uint64_t        ext_call_fast;            /* 0xdc8 */
+    uint64_t        percpu_offset;            /* 0xdd0 */
+    uint64_t        current_task;             /* 0xdd8 */
+    uint32_t        softirq_pending;          /* 0xde0 */
+    uint32_t        pad_0x0de4;               /* 0xde4 */
+    uint64_t        int_clock;                /* 0xde8 */
+    uint8_t         pad12[0xe00-0xdf0];       /* 0xdf0 */
+
+    /* 0xe00 is used as indicator for dump tools */
+    /* whether the kernel died with panic() or not */
+    uint32_t        panic_magic;              /* 0xe00 */
+
+    uint8_t         pad13[0x11b8-0xe04];      /* 0xe04 */
+
+    /* 64 bit extparam used for pfault, diag 250 etc  */
+    uint64_t        ext_params2;               /* 0x11B8 */
+
+    uint8_t         pad14[0x1200-0x11C0];      /* 0x11C0 */
+
+    /* System info area */
+
+    uint64_t        floating_pt_save_area[16]; /* 0x1200 */
+    uint64_t        gpregs_save_area[16];      /* 0x1280 */
+    uint32_t        st_status_fixed_logout[4]; /* 0x1300 */
+    uint8_t         pad15[0x1318-0x1310];      /* 0x1310 */
+    uint32_t        prefixreg_save_area;       /* 0x1318 */
+    uint32_t        fpt_creg_save_area;        /* 0x131c */
+    uint8_t         pad16[0x1324-0x1320];      /* 0x1320 */
+    uint32_t        tod_progreg_save_area;     /* 0x1324 */
+    uint32_t        cpu_timer_save_area[2];    /* 0x1328 */
+    uint32_t        clock_comp_save_area[2];   /* 0x1330 */
+    uint8_t         pad17[0x1340-0x1338];      /* 0x1338 */
+    uint32_t        access_regs_save_area[16]; /* 0x1340 */
+    uint64_t        cregs_save_area[16];       /* 0x1380 */
+
+    /* align to the top of the prefix area */
+
+    uint8_t         pad18[0x2000-0x1400];      /* 0x1400 */
+} __attribute__((packed)) LowCore;
+
+/* STSI */
+#define STSI_LEVEL_MASK         0x00000000f0000000ULL
+#define STSI_LEVEL_CURRENT      0x0000000000000000ULL
+#define STSI_LEVEL_1            0x0000000010000000ULL
+#define STSI_LEVEL_2            0x0000000020000000ULL
+#define STSI_LEVEL_3            0x0000000030000000ULL
+#define STSI_R0_RESERVED_MASK   0x000000000fffff00ULL
+#define STSI_R0_SEL1_MASK       0x00000000000000ffULL
+#define STSI_R1_RESERVED_MASK   0x00000000ffff0000ULL
+#define STSI_R1_SEL2_MASK       0x000000000000ffffULL
+
+/* Basic Machine Configuration */
+struct sysib_111 {
+    uint32_t res1[8];
+    uint8_t  manuf[16];
+    uint8_t  type[4];
+    uint8_t  res2[12];
+    uint8_t  model[16];
+    uint8_t  sequence[16];
+    uint8_t  plant[4];
+    uint8_t  res3[156];
+};
+
+/* Basic Machine CPU */
+struct sysib_121 {
+    uint32_t res1[80];
+    uint8_t  sequence[16];
+    uint8_t  plant[4];
+    uint8_t  res2[2];
+    uint16_t cpu_addr;
+    uint8_t  res3[152];
+};
+
+/* Basic Machine CPUs */
+struct sysib_122 {
+    uint8_t res1[32];
+    uint32_t capability;
+    uint16_t total_cpus;
+    uint16_t active_cpus;
+    uint16_t standby_cpus;
+    uint16_t reserved_cpus;
+    uint16_t adjustments[2026];
+};
+
+/* LPAR CPU */
+struct sysib_221 {
+    uint32_t res1[80];
+    uint8_t  sequence[16];
+    uint8_t  plant[4];
+    uint16_t cpu_id;
+    uint16_t cpu_addr;
+    uint8_t  res3[152];
+};
+
+/* LPAR CPUs */
+struct sysib_222 {
+    uint32_t res1[32];
+    uint16_t lpar_num;
+    uint8_t  res2;
+    uint8_t  lcpuc;
+    uint16_t total_cpus;
+    uint16_t conf_cpus;
+    uint16_t standby_cpus;
+    uint16_t reserved_cpus;
+    uint8_t  name[8];
+    uint32_t caf;
+    uint8_t  res3[16];
+    uint16_t dedicated_cpus;
+    uint16_t shared_cpus;
+    uint8_t  res4[180];
+};
+
+/* VM CPUs */
+struct sysib_322 {
+    uint8_t  res1[31];
+    uint8_t  count;
+    struct {
+        uint8_t  res2[4];
+        uint16_t total_cpus;
+        uint16_t conf_cpus;
+        uint16_t standby_cpus;
+        uint16_t reserved_cpus;
+        uint8_t  name[8];
+        uint32_t caf;
+        uint8_t  cpi[16];
+        uint8_t  res3[24];
+    } vm[8];
+    uint8_t res4[3552];
+};
+
+/* MMU defines */
+#define _ASCE_ORIGIN            ~0xfffULL /* segment table origin             */
+#define _ASCE_SUBSPACE          0x200     /* subspace group control           */
+#define _ASCE_PRIVATE_SPACE     0x100     /* private space control            */
+#define _ASCE_ALT_EVENT         0x80      /* storage alteration event control */
+#define _ASCE_SPACE_SWITCH      0x40      /* space switch event               */
+#define _ASCE_REAL_SPACE        0x20      /* real space control               */
+#define _ASCE_TYPE_MASK         0x0c      /* asce table type mask             */
+#define _ASCE_TYPE_REGION1      0x0c      /* region first table type          */
+#define _ASCE_TYPE_REGION2      0x08      /* region second table type         */
+#define _ASCE_TYPE_REGION3      0x04      /* region third table type          */
+#define _ASCE_TYPE_SEGMENT      0x00      /* segment table type               */
+#define _ASCE_TABLE_LENGTH      0x03      /* region table length              */
+
+#define _REGION_ENTRY_ORIGIN    ~0xfffULL /* region/segment table origin      */
+#define _REGION_ENTRY_INV       0x20      /* invalid region table entry       */
+#define _REGION_ENTRY_TYPE_MASK 0x0c      /* region/segment table type mask   */
+#define _REGION_ENTRY_TYPE_R1   0x0c      /* region first table type          */
+#define _REGION_ENTRY_TYPE_R2   0x08      /* region second table type         */
+#define _REGION_ENTRY_TYPE_R3   0x04      /* region third table type          */
+#define _REGION_ENTRY_LENGTH    0x03      /* region third length              */
+
+#define _SEGMENT_ENTRY_ORIGIN   ~0x7ffULL /* segment table origin             */
+#define _SEGMENT_ENTRY_RO       0x200     /* page protection bit              */
+#define _SEGMENT_ENTRY_INV      0x20      /* invalid segment table entry      */
+
+#define _PAGE_RO        0x200            /* HW read-only bit  */
+#define _PAGE_INVALID   0x400            /* HW invalid bit    */
+
+
+
+/* EBCDIC handling */
+static const uint8_t ebcdic2ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+    0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+    0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+    0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+    0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+    0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+    0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+    0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+    0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+    0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+    0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+    0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+    0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+    0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+    0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+    0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+    0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+    0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+    0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+    0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+    0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+    0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+    0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+    0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
+};
+
+static const uint8_t ascii2ebcdic [] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+    0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+    0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        p[i] = ascii2ebcdic[(int)ascii[i]];
+    }
+}
+
+#define SIGP_SENSE             0x01
+#define SIGP_EXTERNAL_CALL     0x02
+#define SIGP_EMERGENCY         0x03
+#define SIGP_START             0x04
+#define SIGP_STOP              0x05
+#define SIGP_RESTART           0x06
+#define SIGP_STOP_STORE_STATUS 0x09
+#define SIGP_INITIAL_CPU_RESET 0x0b
+#define SIGP_CPU_RESET         0x0c
+#define SIGP_SET_PREFIX        0x0d
+#define SIGP_STORE_STATUS_ADDR 0x0e
+#define SIGP_SET_ARCH          0x12
+
+/* cpu status bits */
+#define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_INCORRECT_STATE   0x00000200UL
+#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
+#define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
+#define SIGP_STAT_STOPPED           0x00000040UL
+#define SIGP_STAT_OPERATOR_INTERV   0x00000020UL
+#define SIGP_STAT_CHECK_STOP        0x00000010UL
+#define SIGP_STAT_INOPERATIVE       0x00000004UL
+#define SIGP_STAT_INVALID_ORDER     0x00000002UL
+#define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
+
+void load_psw(CPUState *env, uint64_t mask, uint64_t addr);
+int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
+                  target_ulong *raddr, int *flags);
+int sclp_service_call(CPUState *env, uint32_t sccb, uint64_t code);
+uint32_t calc_cc(CPUState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+                 uint64_t vr);
+
+#define TARGET_HAS_ICE 1
+
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
+/* Converts ns to s390's clock format */
+static inline uint64_t time2tod(uint64_t ns) {
+    return (ns << 9) / 125;
+}
+
+static inline void cpu_inject_ext(CPUState *env, uint32_t code, uint32_t param,
+                                  uint64_t param64)
+{
+    if (env->ext_index == MAX_EXT_QUEUE - 1) {
+        /* ugh - can't queue anymore. Let's drop. */
+        return;
+    }
+
+    env->ext_index++;
+    assert(env->ext_index < MAX_EXT_QUEUE);
+
+    env->ext_queue[env->ext_index].code = code;
+    env->ext_queue[env->ext_index].param = param;
+    env->ext_queue[env->ext_index].param64 = param64;
+
+    env->pending_int |= INTERRUPT_EXT;
+    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+}
 
 #endif
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ae7dc56..2643460 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -182,8 +182,8 @@ int kvm_arch_process_async_events(CPUState *env)
     return 0;
 }
 
-static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
-                                        uint64_t parm64, int vm)
+void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
+                                 uint64_t parm64, int vm)
 {
     struct kvm_s390_interrupt kvmint;
     int r;
@@ -218,7 +218,7 @@ void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
                                 token, 1);
 }
 
-static void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
+void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
 {
     kvm_s390_interrupt_internal(env, type, code, 0, 0);
 }
@@ -237,7 +237,8 @@ static void setcc(CPUState *env, uint64_t cc)
     env->psw.mask |= (cc & 3) << 44;
 }
 
-static int sclp_service_call(CPUState *env, struct kvm_run *run, uint16_t ipbh0)
+static int kvm_sclp_service_call(CPUState *env, struct kvm_run *run,
+                                 uint16_t ipbh0)
 {
     uint32_t sccb;
     uint64_t code;
@@ -287,7 +288,7 @@ static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
     dprintf("KVM: PRIV: %d\n", ipa1);
     switch (ipa1) {
         case PRIV_SCLP_CALL:
-            r = sclp_service_call(env, run, ipbh0);
+            r = kvm_sclp_service_call(env, run, ipbh0);
             break;
         default:
             dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
@@ -300,12 +301,10 @@ static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
 
 static int handle_hypercall(CPUState *env, struct kvm_run *run)
 {
-    int r;
-
     cpu_synchronize_state(env);
-    r = s390_virtio_hypercall(env);
+    env->regs[2] = s390_virtio_hypercall(env, env->regs[2], env->regs[1]);
 
-    return r;
+    return 0;
 }
 
 static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d33bfb1..2cb893f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -36,7 +36,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
         }
     }
     for (i = 0; i < 16; i++) {
-        cpu_fprintf(f, "F%02d=%016lx", i, (long)env->fregs[i].i);
+        cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
         if ((i % 4) == 3) {
             cpu_fprintf(f, "\n");
         } else {
commit 36d8d02dc8c45780cae74e2ba7a6135b95c16f81
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 18 11:46:41 2011 -0600

    PXE: Refresh all PXE ROMs from the ipxe submodule
    
    Add script to make this easy to repeat later.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/pc-bios/README b/pc-bios/README
index 646a31a..fe221a9 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -18,16 +18,15 @@
   https://github.com/dgibson/SLOF, and the image currently in qemu is
   built from git tag qemu-slof-20110323.
 
-- The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
-
-  e1000 8086:100E
-  eepro100 8086:1209 (also used for 8086:1229 and 8086:2449)
-  ns8390 1050:0940
-  pcnet32 1022:2000
-  rtl8139 10ec:8139
-  virtio 1af4:1000
-
-  http://rom-o-matic.net/
+- The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
+  Sources available at http://ipxe.org.  Vendor:Device ID -> ROM mapping:
+
+	8086:100e -> pxe-e1000.rom
+	8086:1209 -> pxe-eepro100.rom
+	1050:0940 -> pxe-ne2k_pci.rom
+	1022:2000 -> pxe-pcnet.rom
+	10ec:8139 -> pxe-rtl8139.rom
+	1af4:1000 -> pxe-virtio.rom
 
 - The S390 zipl loader is an addition to the official IBM s390-tools
   package. That fork is maintained in its own git repository at:
diff --git a/pc-bios/pxe-e1000.rom b/pc-bios/pxe-e1000.rom
index 7ac744e..2e5f8b2 100644
Binary files a/pc-bios/pxe-e1000.rom and b/pc-bios/pxe-e1000.rom differ
diff --git a/pc-bios/pxe-eepro100.rom b/pc-bios/pxe-eepro100.rom
index 2ca59ec..d292e8f 100644
Binary files a/pc-bios/pxe-eepro100.rom and b/pc-bios/pxe-eepro100.rom differ
diff --git a/pc-bios/pxe-ne2k_pci.rom b/pc-bios/pxe-ne2k_pci.rom
index 5cb68ab..62010cb 100644
Binary files a/pc-bios/pxe-ne2k_pci.rom and b/pc-bios/pxe-ne2k_pci.rom differ
diff --git a/pc-bios/pxe-pcnet.rom b/pc-bios/pxe-pcnet.rom
index 7a54bab..512d6d4 100644
Binary files a/pc-bios/pxe-pcnet.rom and b/pc-bios/pxe-pcnet.rom differ
diff --git a/pc-bios/pxe-rtl8139.rom b/pc-bios/pxe-rtl8139.rom
index db7d76d..67c77fb 100644
Binary files a/pc-bios/pxe-rtl8139.rom and b/pc-bios/pxe-rtl8139.rom differ
diff --git a/pc-bios/pxe-virtio.rom b/pc-bios/pxe-virtio.rom
index 6dde514..b1ec909 100644
Binary files a/pc-bios/pxe-virtio.rom and b/pc-bios/pxe-virtio.rom differ
diff --git a/scripts/refresh-pxe-roms.sh b/scripts/refresh-pxe-roms.sh
new file mode 100755
index 0000000..14d5860
--- /dev/null
+++ b/scripts/refresh-pxe-roms.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+# PXE ROM build script
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#   Authors: Alex Williamson <alex.williamson at redhat.com>
+#
+# Usage: Run from root of qemu tree
+# ./scripts/refresh-pxe-roms.sh
+
+QEMU_DIR=$PWD
+ROM_DIR="pc-bios"
+BUILD_DIR="roms/ipxe"
+LOCAL_CONFIG="src/config/local/general.h"
+
+function cleanup ()
+{
+    if [ -n "$SAVED_CONFIG" ]; then
+        cp "$SAVED_CONFIG" "$BUILD_DIR"/"$LOCAL_CONFIG"
+        rm "$SAVED_CONFIG"
+    fi
+    cd "$QEMU_DIR"
+}
+
+function make_rom ()
+{
+    cd "$BUILD_DIR"/src
+
+    BUILD_LOG=$(mktemp)
+
+    echo Building "$2"...
+    make bin/"$1".rom > "$BUILD_LOG" 2>&1
+    if [ $? -ne 0 ]; then
+        echo Build failed
+        tail --lines=100 "$BUILD_LOG"
+        rm "$BUILD_LOG"
+        cleanup
+        exit 1
+    fi
+    rm "$BUILD_LOG"
+
+    cp bin/"$1".rom "$QEMU_DIR"/"$ROM_DIR"/"$2"
+
+    cd "$QEMU_DIR"
+}
+
+if [ ! -d "$QEMU_DIR"/"$ROM_DIR" ]; then
+    echo "error: can't find $ROM_DIR directory," \
+         "run me from the root of the qemu tree"
+    exit 1
+fi
+
+if [ ! -d "$BUILD_DIR"/src ]; then
+    echo "error: $BUILD_DIR not populated, try:"
+    echo "  git submodule init $BUILD_DIR"
+    echo "  git submodule update $BUILD_DIR"
+    exit 1
+fi
+
+if [ -e "$BUILD_DIR"/"$LOCAL_CONFIG" ]; then
+    SAVED_CONFIG=$(mktemp)
+    cp "$BUILD_DIR"/"$LOCAL_CONFIG" "$SAVED_CONFIG"
+fi
+
+echo "#undef BANNER_TIMEOUT" > "$BUILD_DIR"/"$LOCAL_CONFIG"
+echo "#define BANNER_TIMEOUT 0" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+
+IPXE_VERSION=$(cd "$BUILD_DIR" && git describe --tags)
+if [ -z "$IPXE_VERSION" ]; then
+    echo "error: unable to retrieve git version"
+    cleanup
+    exit 1
+fi
+
+echo "#undef PRODUCT_NAME" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+echo "#define PRODUCT_NAME \"iPXE $IPXE_VERSION\"" >> "$BUILD_DIR"/"$LOCAL_CONFIG"
+
+make_rom 8086100e pxe-e1000.rom
+make_rom 80861209 pxe-eepro100.rom
+make_rom 10500940 pxe-ne2k_pci.rom
+make_rom 10222000 pxe-pcnet.rom
+make_rom 10ec8139 pxe-rtl8139.rom
+make_rom 1af41000 pxe-virtio.rom
+
+echo done
+cleanup
commit 5ee8ad71e159e724e2fa1af6b2c502668179502a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 18 11:46:01 2011 -0600

    PXE: Use consistent naming for PXE ROMs
    
    And add missing ROMs to tarbin build target.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/Makefile b/Makefile
index fa93be5..9df4fff 100644
--- a/Makefile
+++ b/Makefile
@@ -177,10 +177,8 @@ ifdef INSTALL_BLOBS
 BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
 vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
-gpxe-eepro100-80861209.rom \
-pxe-e1000.bin \
-pxe-ne2k_pci.bin pxe-pcnet.bin \
-pxe-rtl8139.bin pxe-virtio.bin \
+pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
+pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin \
 s390-zipl.rom \
@@ -326,10 +324,12 @@ tarbin:
 	$(datadir)/openbios-sparc32 \
 	$(datadir)/openbios-sparc64 \
 	$(datadir)/openbios-ppc \
-	$(datadir)/pxe-ne2k_pci.bin \
-	$(datadir)/pxe-rtl8139.bin \
-	$(datadir)/pxe-pcnet.bin \
-	$(datadir)/pxe-e1000.bin \
+	$(datadir)/pxe-e1000.rom \
+	$(datadir)/pxe-eepro100.rom \
+	$(datadir)/pxe-ne2k_pci.rom \
+	$(datadir)/pxe-pcnet.rom \
+	$(datadir)/pxe-rtl8139.rom \
+	$(datadir)/pxe-virtio.rom \
 	$(docdir)/qemu-doc.html \
 	$(docdir)/qemu-tech.html \
 	$(mandir)/man1/qemu.1 \
diff --git a/configure b/configure
index ae97e11..813ef7a 100755
--- a/configure
+++ b/configure
@@ -3445,7 +3445,7 @@ FILES="Makefile tests/Makefile"
 FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
     FILES="$FILES pc-bios/`basename $bios_file`"
 done
 mkdir -p $DIRS
diff --git a/hw/e1000.c b/hw/e1000.c
index fe3e812..f160bfc 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1220,7 +1220,7 @@ static PCIDeviceInfo e1000_info = {
     .qdev.vmsd  = &vmstate_e1000,
     .init       = pci_e1000_init,
     .exit       = pci_e1000_uninit,
-    .romfile    = "pxe-e1000.bin",
+    .romfile    = "pxe-e1000.rom",
     .qdev.props = (Property[]) {
         DEFINE_NIC_PROPERTIES(E1000State, conf),
         DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/eepro100.c b/hw/eepro100.c
index edf48f6..369ad7f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -2054,7 +2054,7 @@ static void eepro100_register_devices(void)
         PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
         /* We use the same rom file for all device ids.
            QEMU fixes the device id during rom load. */
-        pci_dev->romfile = "gpxe-eepro100-80861209.rom";
+        pci_dev->romfile = "pxe-eepro100.rom";
         pci_dev->init = e100_nic_init;
         pci_dev->exit = pci_nic_uninit;
         pci_dev->qdev.props = e100_properties;
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 5966359..b668ad1 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -742,7 +742,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
     if (!pci_dev->qdev.hotplugged) {
         static int loaded = 0;
         if (!loaded) {
-            rom_add_option("pxe-ne2k_pci.bin", -1);
+            rom_add_option("pxe-ne2k_pci.rom", -1);
             loaded = 1;
         }
     }
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 339a401..40ee29d 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -310,7 +310,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     if (!pci_dev->qdev.hotplugged) {
         static int loaded = 0;
         if (!loaded) {
-            rom_add_option("pxe-pcnet.bin", -1);
+            rom_add_option("pxe-pcnet.rom", -1);
             loaded = 1;
         }
     }
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d545933..8790a00 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3484,7 +3484,7 @@ static PCIDeviceInfo rtl8139_info = {
     .qdev.vmsd  = &vmstate_rtl8139,
     .init       = pci_rtl8139_init,
     .exit       = pci_rtl8139_uninit,
-    .romfile    = "pxe-rtl8139.bin",
+    .romfile    = "pxe-rtl8139.rom",
     .qdev.props = (Property[]) {
         DEFINE_NIC_PROPERTIES(RTL8139State, conf),
         DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 555f23f..c19629d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -877,7 +877,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.size  = sizeof(VirtIOPCIProxy),
         .init       = virtio_net_init_pci,
         .exit       = virtio_net_exit_pci,
-        .romfile    = "pxe-virtio.bin",
+        .romfile    = "pxe-virtio.rom",
         .qdev.props = (Property[]) {
             DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
                             VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
diff --git a/pc-bios/gpxe-eepro100-80861209.rom b/pc-bios/gpxe-eepro100-80861209.rom
deleted file mode 100644
index 2ca59ec..0000000
Binary files a/pc-bios/gpxe-eepro100-80861209.rom and /dev/null differ
diff --git a/pc-bios/pxe-e1000.bin b/pc-bios/pxe-e1000.bin
deleted file mode 100644
index 7ac744e..0000000
Binary files a/pc-bios/pxe-e1000.bin and /dev/null differ
diff --git a/pc-bios/pxe-e1000.rom b/pc-bios/pxe-e1000.rom
new file mode 100644
index 0000000..7ac744e
Binary files /dev/null and b/pc-bios/pxe-e1000.rom differ
diff --git a/pc-bios/pxe-eepro100.rom b/pc-bios/pxe-eepro100.rom
new file mode 100644
index 0000000..2ca59ec
Binary files /dev/null and b/pc-bios/pxe-eepro100.rom differ
diff --git a/pc-bios/pxe-ne2k_pci.bin b/pc-bios/pxe-ne2k_pci.bin
deleted file mode 100644
index 5cb68ab..0000000
Binary files a/pc-bios/pxe-ne2k_pci.bin and /dev/null differ
diff --git a/pc-bios/pxe-ne2k_pci.rom b/pc-bios/pxe-ne2k_pci.rom
new file mode 100644
index 0000000..5cb68ab
Binary files /dev/null and b/pc-bios/pxe-ne2k_pci.rom differ
diff --git a/pc-bios/pxe-pcnet.bin b/pc-bios/pxe-pcnet.bin
deleted file mode 100644
index 7a54bab..0000000
Binary files a/pc-bios/pxe-pcnet.bin and /dev/null differ
diff --git a/pc-bios/pxe-pcnet.rom b/pc-bios/pxe-pcnet.rom
new file mode 100644
index 0000000..7a54bab
Binary files /dev/null and b/pc-bios/pxe-pcnet.rom differ
diff --git a/pc-bios/pxe-rtl8139.bin b/pc-bios/pxe-rtl8139.bin
deleted file mode 100644
index db7d76d..0000000
Binary files a/pc-bios/pxe-rtl8139.bin and /dev/null differ
diff --git a/pc-bios/pxe-rtl8139.rom b/pc-bios/pxe-rtl8139.rom
new file mode 100644
index 0000000..db7d76d
Binary files /dev/null and b/pc-bios/pxe-rtl8139.rom differ
diff --git a/pc-bios/pxe-virtio.bin b/pc-bios/pxe-virtio.bin
deleted file mode 100644
index 6dde514..0000000
Binary files a/pc-bios/pxe-virtio.bin and /dev/null differ
diff --git a/pc-bios/pxe-virtio.rom b/pc-bios/pxe-virtio.rom
new file mode 100644
index 0000000..6dde514
Binary files /dev/null and b/pc-bios/pxe-virtio.rom differ
commit 7b59220ef31a9c8758f8de16e6aaf3fc14b6540c
Author: Lluís <xscript at gmx.net>
Date:   Wed Apr 13 18:38:24 2011 +0200

    move helpers.h to helper.h
    
    This provides a consistent naming scheme across all targets.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index a0ec643..12127de 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5,7 +5,7 @@
 #include "cpu.h"
 #include "exec-all.h"
 #include "gdbstub.h"
-#include "helpers.h"
+#include "helper.h"
 #include "qemu-common.h"
 #include "host-utils.h"
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-arm/helper.h b/target-arm/helper.h
new file mode 100644
index 0000000..ae701e8
--- /dev/null
+++ b/target-arm/helper.h
@@ -0,0 +1,475 @@
+#include "def-helper.h"
+
+DEF_HELPER_1(clz, i32, i32)
+DEF_HELPER_1(sxtb16, i32, i32)
+DEF_HELPER_1(uxtb16, i32, i32)
+
+DEF_HELPER_2(add_setq, i32, i32, i32)
+DEF_HELPER_2(add_saturate, i32, i32, i32)
+DEF_HELPER_2(sub_saturate, i32, i32, i32)
+DEF_HELPER_2(add_usaturate, i32, i32, i32)
+DEF_HELPER_2(sub_usaturate, i32, i32, i32)
+DEF_HELPER_1(double_saturate, i32, s32)
+DEF_HELPER_2(sdiv, s32, s32, s32)
+DEF_HELPER_2(udiv, i32, i32, i32)
+DEF_HELPER_1(rbit, i32, i32)
+DEF_HELPER_1(abs, i32, i32)
+
+#define PAS_OP(pfx)  \
+    DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \
+    DEF_HELPER_3(pfx ## sub8, i32, i32, i32, ptr) \
+    DEF_HELPER_3(pfx ## sub16, i32, i32, i32, ptr) \
+    DEF_HELPER_3(pfx ## add16, i32, i32, i32, ptr) \
+    DEF_HELPER_3(pfx ## addsubx, i32, i32, i32, ptr) \
+    DEF_HELPER_3(pfx ## subaddx, i32, i32, i32, ptr)
+
+PAS_OP(s)
+PAS_OP(u)
+#undef PAS_OP
+
+#define PAS_OP(pfx)  \
+    DEF_HELPER_2(pfx ## add8, i32, i32, i32) \
+    DEF_HELPER_2(pfx ## sub8, i32, i32, i32) \
+    DEF_HELPER_2(pfx ## sub16, i32, i32, i32) \
+    DEF_HELPER_2(pfx ## add16, i32, i32, i32) \
+    DEF_HELPER_2(pfx ## addsubx, i32, i32, i32) \
+    DEF_HELPER_2(pfx ## subaddx, i32, i32, i32)
+PAS_OP(q)
+PAS_OP(sh)
+PAS_OP(uq)
+PAS_OP(uh)
+#undef PAS_OP
+
+DEF_HELPER_2(ssat, i32, i32, i32)
+DEF_HELPER_2(usat, i32, i32, i32)
+DEF_HELPER_2(ssat16, i32, i32, i32)
+DEF_HELPER_2(usat16, i32, i32, i32)
+
+DEF_HELPER_2(usad8, i32, i32, i32)
+
+DEF_HELPER_1(logicq_cc, i32, i64)
+
+DEF_HELPER_3(sel_flags, i32, i32, i32, i32)
+DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_0(wfi, void)
+
+DEF_HELPER_2(cpsr_write, void, i32, i32)
+DEF_HELPER_0(cpsr_read, i32)
+
+DEF_HELPER_3(v7m_msr, void, env, i32, i32)
+DEF_HELPER_2(v7m_mrs, i32, env, i32)
+
+DEF_HELPER_3(set_cp15, void, env, i32, i32)
+DEF_HELPER_2(get_cp15, i32, env, i32)
+
+DEF_HELPER_3(set_cp, void, env, i32, i32)
+DEF_HELPER_2(get_cp, i32, env, i32)
+
+DEF_HELPER_2(get_r13_banked, i32, env, i32)
+DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
+
+DEF_HELPER_1(get_user_reg, i32, i32)
+DEF_HELPER_2(set_user_reg, void, i32, i32)
+
+DEF_HELPER_1(vfp_get_fpscr, i32, env)
+DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
+
+DEF_HELPER_3(vfp_adds, f32, f32, f32, env)
+DEF_HELPER_3(vfp_addd, f64, f64, f64, env)
+DEF_HELPER_3(vfp_subs, f32, f32, f32, env)
+DEF_HELPER_3(vfp_subd, f64, f64, f64, env)
+DEF_HELPER_3(vfp_muls, f32, f32, f32, env)
+DEF_HELPER_3(vfp_muld, f64, f64, f64, env)
+DEF_HELPER_3(vfp_divs, f32, f32, f32, env)
+DEF_HELPER_3(vfp_divd, f64, f64, f64, env)
+DEF_HELPER_1(vfp_negs, f32, f32)
+DEF_HELPER_1(vfp_negd, f64, f64)
+DEF_HELPER_1(vfp_abss, f32, f32)
+DEF_HELPER_1(vfp_absd, f64, f64)
+DEF_HELPER_2(vfp_sqrts, f32, f32, env)
+DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
+DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
+DEF_HELPER_3(vfp_cmpd, void, f64, f64, env)
+DEF_HELPER_3(vfp_cmpes, void, f32, f32, env)
+DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
+
+DEF_HELPER_2(vfp_fcvtds, f64, f32, env)
+DEF_HELPER_2(vfp_fcvtsd, f32, f64, env)
+
+DEF_HELPER_2(vfp_uitos, f32, i32, env)
+DEF_HELPER_2(vfp_uitod, f64, i32, env)
+DEF_HELPER_2(vfp_sitos, f32, i32, env)
+DEF_HELPER_2(vfp_sitod, f64, i32, env)
+
+DEF_HELPER_2(vfp_touis, i32, f32, env)
+DEF_HELPER_2(vfp_touid, i32, f64, env)
+DEF_HELPER_2(vfp_touizs, i32, f32, env)
+DEF_HELPER_2(vfp_touizd, i32, f64, env)
+DEF_HELPER_2(vfp_tosis, i32, f32, env)
+DEF_HELPER_2(vfp_tosid, i32, f64, env)
+DEF_HELPER_2(vfp_tosizs, i32, f32, env)
+DEF_HELPER_2(vfp_tosizd, i32, f64, env)
+
+DEF_HELPER_3(vfp_toshs, i32, f32, i32, env)
+DEF_HELPER_3(vfp_tosls, i32, f32, i32, env)
+DEF_HELPER_3(vfp_touhs, i32, f32, i32, env)
+DEF_HELPER_3(vfp_touls, i32, f32, i32, env)
+DEF_HELPER_3(vfp_toshd, i64, f64, i32, env)
+DEF_HELPER_3(vfp_tosld, i64, f64, i32, env)
+DEF_HELPER_3(vfp_touhd, i64, f64, i32, env)
+DEF_HELPER_3(vfp_tould, i64, f64, i32, env)
+DEF_HELPER_3(vfp_shtos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_sltos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_uhtos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_ultos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_shtod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_sltod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_uhtod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_ultod, f64, i64, i32, env)
+
+DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
+DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
+DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
+DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
+
+DEF_HELPER_3(recps_f32, f32, f32, f32, env)
+DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
+DEF_HELPER_2(recpe_f32, f32, f32, env)
+DEF_HELPER_2(rsqrte_f32, f32, f32, env)
+DEF_HELPER_2(recpe_u32, i32, i32, env)
+DEF_HELPER_2(rsqrte_u32, i32, i32, env)
+DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32)
+
+DEF_HELPER_2(add_cc, i32, i32, i32)
+DEF_HELPER_2(adc_cc, i32, i32, i32)
+DEF_HELPER_2(sub_cc, i32, i32, i32)
+DEF_HELPER_2(sbc_cc, i32, i32, i32)
+
+DEF_HELPER_2(shl, i32, i32, i32)
+DEF_HELPER_2(shr, i32, i32, i32)
+DEF_HELPER_2(sar, i32, i32, i32)
+DEF_HELPER_2(shl_cc, i32, i32, i32)
+DEF_HELPER_2(shr_cc, i32, i32, i32)
+DEF_HELPER_2(sar_cc, i32, i32, i32)
+DEF_HELPER_2(ror_cc, i32, i32, i32)
+
+/* neon_helper.c */
+DEF_HELPER_2(neon_qadd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qadd_s64, i64, i64, i64)
+DEF_HELPER_2(neon_qsub_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qsub_s64, i64, i64, i64)
+
+DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
+DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_hadd_s16, i32, i32, i32)
+DEF_HELPER_2(neon_hadd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_hadd_s32, s32, s32, s32)
+DEF_HELPER_2(neon_hadd_u32, i32, i32, i32)
+DEF_HELPER_2(neon_rhadd_s8, i32, i32, i32)
+DEF_HELPER_2(neon_rhadd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_rhadd_s16, i32, i32, i32)
+DEF_HELPER_2(neon_rhadd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_rhadd_s32, s32, s32, s32)
+DEF_HELPER_2(neon_rhadd_u32, i32, i32, i32)
+DEF_HELPER_2(neon_hsub_s8, i32, i32, i32)
+DEF_HELPER_2(neon_hsub_u8, i32, i32, i32)
+DEF_HELPER_2(neon_hsub_s16, i32, i32, i32)
+DEF_HELPER_2(neon_hsub_u16, i32, i32, i32)
+DEF_HELPER_2(neon_hsub_s32, s32, s32, s32)
+DEF_HELPER_2(neon_hsub_u32, i32, i32, i32)
+
+DEF_HELPER_2(neon_cgt_u8, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_s8, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_u16, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_s16, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_u32, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_s32, i32, i32, i32)
+DEF_HELPER_2(neon_cge_u8, i32, i32, i32)
+DEF_HELPER_2(neon_cge_s8, i32, i32, i32)
+DEF_HELPER_2(neon_cge_u16, i32, i32, i32)
+DEF_HELPER_2(neon_cge_s16, i32, i32, i32)
+DEF_HELPER_2(neon_cge_u32, i32, i32, i32)
+DEF_HELPER_2(neon_cge_s32, i32, i32, i32)
+
+DEF_HELPER_2(neon_min_u8, i32, i32, i32)
+DEF_HELPER_2(neon_min_s8, i32, i32, i32)
+DEF_HELPER_2(neon_min_u16, i32, i32, i32)
+DEF_HELPER_2(neon_min_s16, i32, i32, i32)
+DEF_HELPER_2(neon_min_u32, i32, i32, i32)
+DEF_HELPER_2(neon_min_s32, i32, i32, i32)
+DEF_HELPER_2(neon_max_u8, i32, i32, i32)
+DEF_HELPER_2(neon_max_s8, i32, i32, i32)
+DEF_HELPER_2(neon_max_u16, i32, i32, i32)
+DEF_HELPER_2(neon_max_s16, i32, i32, i32)
+DEF_HELPER_2(neon_max_u32, i32, i32, i32)
+DEF_HELPER_2(neon_max_s32, i32, i32, i32)
+DEF_HELPER_2(neon_pmin_u8, i32, i32, i32)
+DEF_HELPER_2(neon_pmin_s8, i32, i32, i32)
+DEF_HELPER_2(neon_pmin_u16, i32, i32, i32)
+DEF_HELPER_2(neon_pmin_s16, i32, i32, i32)
+DEF_HELPER_2(neon_pmax_u8, i32, i32, i32)
+DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
+DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
+DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
+
+DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
+DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
+DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
+DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
+
+DEF_HELPER_2(neon_shl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_shl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_shl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_shl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_shl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_shl_s64, i64, i64, i64)
+DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_rshl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_rshl_s64, i64, i64, i64)
+DEF_HELPER_2(neon_qshl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qshl_s64, i64, i64, i64)
+DEF_HELPER_2(neon_qshlu_s8, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s16, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s32, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s64, i64, i64, i64);
+DEF_HELPER_2(neon_qrshl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qrshl_s64, i64, i64, i64)
+
+DEF_HELPER_2(neon_add_u8, i32, i32, i32)
+DEF_HELPER_2(neon_add_u16, i32, i32, i32)
+DEF_HELPER_2(neon_padd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_padd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_sub_u8, i32, i32, i32)
+DEF_HELPER_2(neon_sub_u16, i32, i32, i32)
+DEF_HELPER_2(neon_mul_u8, i32, i32, i32)
+DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
+DEF_HELPER_2(neon_mul_p8, i32, i32, i32)
+DEF_HELPER_2(neon_mull_p8, i64, i32, i32)
+
+DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
+DEF_HELPER_2(neon_tst_u16, i32, i32, i32)
+DEF_HELPER_2(neon_tst_u32, i32, i32, i32)
+DEF_HELPER_2(neon_ceq_u8, i32, i32, i32)
+DEF_HELPER_2(neon_ceq_u16, i32, i32, i32)
+DEF_HELPER_2(neon_ceq_u32, i32, i32, i32)
+
+DEF_HELPER_1(neon_abs_s8, i32, i32)
+DEF_HELPER_1(neon_abs_s16, i32, i32)
+DEF_HELPER_1(neon_clz_u8, i32, i32)
+DEF_HELPER_1(neon_clz_u16, i32, i32)
+DEF_HELPER_1(neon_cls_s8, i32, i32)
+DEF_HELPER_1(neon_cls_s16, i32, i32)
+DEF_HELPER_1(neon_cls_s32, i32, i32)
+DEF_HELPER_1(neon_cnt_u8, i32, i32)
+
+DEF_HELPER_2(neon_qdmulh_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qrdmulh_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qdmulh_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qrdmulh_s32, i32, i32, i32)
+
+DEF_HELPER_1(neon_narrow_u8, i32, i64)
+DEF_HELPER_1(neon_narrow_u16, i32, i64)
+DEF_HELPER_1(neon_unarrow_sat8, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u8, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s8, i32, i64)
+DEF_HELPER_1(neon_unarrow_sat16, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u16, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s16, i32, i64)
+DEF_HELPER_1(neon_unarrow_sat32, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u32, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s32, i32, i64)
+DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
+DEF_HELPER_1(neon_narrow_high_u16, i32, i64)
+DEF_HELPER_1(neon_narrow_round_high_u8, i32, i64)
+DEF_HELPER_1(neon_narrow_round_high_u16, i32, i64)
+DEF_HELPER_1(neon_widen_u8, i64, i32)
+DEF_HELPER_1(neon_widen_s8, i64, i32)
+DEF_HELPER_1(neon_widen_u16, i64, i32)
+DEF_HELPER_1(neon_widen_s16, i64, i32)
+
+DEF_HELPER_2(neon_addl_u16, i64, i64, i64)
+DEF_HELPER_2(neon_addl_u32, i64, i64, i64)
+DEF_HELPER_2(neon_paddl_u16, i64, i64, i64)
+DEF_HELPER_2(neon_paddl_u32, i64, i64, i64)
+DEF_HELPER_2(neon_subl_u16, i64, i64, i64)
+DEF_HELPER_2(neon_subl_u32, i64, i64, i64)
+DEF_HELPER_2(neon_addl_saturate_s32, i64, i64, i64)
+DEF_HELPER_2(neon_addl_saturate_s64, i64, i64, i64)
+DEF_HELPER_2(neon_abdl_u16, i64, i32, i32)
+DEF_HELPER_2(neon_abdl_s16, i64, i32, i32)
+DEF_HELPER_2(neon_abdl_u32, i64, i32, i32)
+DEF_HELPER_2(neon_abdl_s32, i64, i32, i32)
+DEF_HELPER_2(neon_abdl_u64, i64, i32, i32)
+DEF_HELPER_2(neon_abdl_s64, i64, i32, i32)
+DEF_HELPER_2(neon_mull_u8, i64, i32, i32)
+DEF_HELPER_2(neon_mull_s8, i64, i32, i32)
+DEF_HELPER_2(neon_mull_u16, i64, i32, i32)
+DEF_HELPER_2(neon_mull_s16, i64, i32, i32)
+
+DEF_HELPER_1(neon_negl_u16, i64, i64)
+DEF_HELPER_1(neon_negl_u32, i64, i64)
+DEF_HELPER_1(neon_negl_u64, i64, i64)
+
+DEF_HELPER_1(neon_qabs_s8, i32, i32)
+DEF_HELPER_1(neon_qabs_s16, i32, i32)
+DEF_HELPER_1(neon_qabs_s32, i32, i32)
+DEF_HELPER_1(neon_qneg_s8, i32, i32)
+DEF_HELPER_1(neon_qneg_s16, i32, i32)
+DEF_HELPER_1(neon_qneg_s32, i32, i32)
+
+DEF_HELPER_2(neon_min_f32, i32, i32, i32)
+DEF_HELPER_2(neon_max_f32, i32, i32, i32)
+DEF_HELPER_2(neon_abd_f32, i32, i32, i32)
+DEF_HELPER_2(neon_add_f32, i32, i32, i32)
+DEF_HELPER_2(neon_sub_f32, i32, i32, i32)
+DEF_HELPER_2(neon_mul_f32, i32, i32, i32)
+DEF_HELPER_2(neon_ceq_f32, i32, i32, i32)
+DEF_HELPER_2(neon_cge_f32, i32, i32, i32)
+DEF_HELPER_2(neon_cgt_f32, i32, i32, i32)
+DEF_HELPER_2(neon_acge_f32, i32, i32, i32)
+DEF_HELPER_2(neon_acgt_f32, i32, i32, i32)
+
+/* iwmmxt_helper.c */
+DEF_HELPER_2(iwmmxt_maddsq, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_madduq, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_sadb, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_sadw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_mulslw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_mulshw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_mululw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_muluhw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_macsw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_macuw, i64, i64, i64)
+DEF_HELPER_1(iwmmxt_setpsr_nz, i32, i64)
+
+#define DEF_IWMMXT_HELPER_SIZE(name) \
+DEF_HELPER_2(iwmmxt_##name##b, i64, i64, i64) \
+DEF_HELPER_2(iwmmxt_##name##w, i64, i64, i64) \
+DEF_HELPER_2(iwmmxt_##name##l, i64, i64, i64) \
+
+DEF_IWMMXT_HELPER_SIZE(unpackl)
+DEF_IWMMXT_HELPER_SIZE(unpackh)
+
+DEF_HELPER_1(iwmmxt_unpacklub, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackluw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklul, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhub, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhuw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhul, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsb, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsl, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsb, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsl, i64, i64)
+
+DEF_IWMMXT_HELPER_SIZE(cmpeq)
+DEF_IWMMXT_HELPER_SIZE(cmpgtu)
+DEF_IWMMXT_HELPER_SIZE(cmpgts)
+
+DEF_IWMMXT_HELPER_SIZE(mins)
+DEF_IWMMXT_HELPER_SIZE(minu)
+DEF_IWMMXT_HELPER_SIZE(maxs)
+DEF_IWMMXT_HELPER_SIZE(maxu)
+
+DEF_IWMMXT_HELPER_SIZE(subn)
+DEF_IWMMXT_HELPER_SIZE(addn)
+DEF_IWMMXT_HELPER_SIZE(subu)
+DEF_IWMMXT_HELPER_SIZE(addu)
+DEF_IWMMXT_HELPER_SIZE(subs)
+DEF_IWMMXT_HELPER_SIZE(adds)
+
+DEF_HELPER_2(iwmmxt_avgb0, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgb1, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgw0, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgw1, i64, i64, i64)
+
+DEF_HELPER_2(iwmmxt_msadb, i64, i64, i64)
+
+DEF_HELPER_3(iwmmxt_align, i64, i64, i64, i32)
+DEF_HELPER_4(iwmmxt_insr, i64, i64, i32, i32, i32)
+
+DEF_HELPER_1(iwmmxt_bcstb, i64, i32)
+DEF_HELPER_1(iwmmxt_bcstw, i64, i32)
+DEF_HELPER_1(iwmmxt_bcstl, i64, i32)
+
+DEF_HELPER_1(iwmmxt_addcb, i64, i64)
+DEF_HELPER_1(iwmmxt_addcw, i64, i64)
+DEF_HELPER_1(iwmmxt_addcl, i64, i64)
+
+DEF_HELPER_1(iwmmxt_msbb, i32, i64)
+DEF_HELPER_1(iwmmxt_msbw, i32, i64)
+DEF_HELPER_1(iwmmxt_msbl, i32, i64)
+
+DEF_HELPER_2(iwmmxt_srlw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_srll, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_srlq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sllw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_slll, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sllq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sraw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sral, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sraq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorl, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_shufh, i64, i64, i32)
+
+DEF_HELPER_2(iwmmxt_packuw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packul, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packuq, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsl, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsq, i64, i64, i64)
+
+DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
+DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
+DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
+
+DEF_HELPER_2(set_teecr, void, env, i32)
+
+DEF_HELPER_2(neon_unzip8, void, i32, i32)
+DEF_HELPER_2(neon_unzip16, void, i32, i32)
+DEF_HELPER_2(neon_qunzip8, void, i32, i32)
+DEF_HELPER_2(neon_qunzip16, void, i32, i32)
+DEF_HELPER_2(neon_qunzip32, void, i32, i32)
+DEF_HELPER_2(neon_zip8, void, i32, i32)
+DEF_HELPER_2(neon_zip16, void, i32, i32)
+DEF_HELPER_2(neon_qzip8, void, i32, i32)
+DEF_HELPER_2(neon_qzip16, void, i32, i32)
+DEF_HELPER_2(neon_qzip32, void, i32, i32)
+
+#include "def-helper.h"
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
deleted file mode 100644
index ae701e8..0000000
--- a/target-arm/helpers.h
+++ /dev/null
@@ -1,475 +0,0 @@
-#include "def-helper.h"
-
-DEF_HELPER_1(clz, i32, i32)
-DEF_HELPER_1(sxtb16, i32, i32)
-DEF_HELPER_1(uxtb16, i32, i32)
-
-DEF_HELPER_2(add_setq, i32, i32, i32)
-DEF_HELPER_2(add_saturate, i32, i32, i32)
-DEF_HELPER_2(sub_saturate, i32, i32, i32)
-DEF_HELPER_2(add_usaturate, i32, i32, i32)
-DEF_HELPER_2(sub_usaturate, i32, i32, i32)
-DEF_HELPER_1(double_saturate, i32, s32)
-DEF_HELPER_2(sdiv, s32, s32, s32)
-DEF_HELPER_2(udiv, i32, i32, i32)
-DEF_HELPER_1(rbit, i32, i32)
-DEF_HELPER_1(abs, i32, i32)
-
-#define PAS_OP(pfx)  \
-    DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \
-    DEF_HELPER_3(pfx ## sub8, i32, i32, i32, ptr) \
-    DEF_HELPER_3(pfx ## sub16, i32, i32, i32, ptr) \
-    DEF_HELPER_3(pfx ## add16, i32, i32, i32, ptr) \
-    DEF_HELPER_3(pfx ## addsubx, i32, i32, i32, ptr) \
-    DEF_HELPER_3(pfx ## subaddx, i32, i32, i32, ptr)
-
-PAS_OP(s)
-PAS_OP(u)
-#undef PAS_OP
-
-#define PAS_OP(pfx)  \
-    DEF_HELPER_2(pfx ## add8, i32, i32, i32) \
-    DEF_HELPER_2(pfx ## sub8, i32, i32, i32) \
-    DEF_HELPER_2(pfx ## sub16, i32, i32, i32) \
-    DEF_HELPER_2(pfx ## add16, i32, i32, i32) \
-    DEF_HELPER_2(pfx ## addsubx, i32, i32, i32) \
-    DEF_HELPER_2(pfx ## subaddx, i32, i32, i32)
-PAS_OP(q)
-PAS_OP(sh)
-PAS_OP(uq)
-PAS_OP(uh)
-#undef PAS_OP
-
-DEF_HELPER_2(ssat, i32, i32, i32)
-DEF_HELPER_2(usat, i32, i32, i32)
-DEF_HELPER_2(ssat16, i32, i32, i32)
-DEF_HELPER_2(usat16, i32, i32, i32)
-
-DEF_HELPER_2(usad8, i32, i32, i32)
-
-DEF_HELPER_1(logicq_cc, i32, i64)
-
-DEF_HELPER_3(sel_flags, i32, i32, i32, i32)
-DEF_HELPER_1(exception, void, i32)
-DEF_HELPER_0(wfi, void)
-
-DEF_HELPER_2(cpsr_write, void, i32, i32)
-DEF_HELPER_0(cpsr_read, i32)
-
-DEF_HELPER_3(v7m_msr, void, env, i32, i32)
-DEF_HELPER_2(v7m_mrs, i32, env, i32)
-
-DEF_HELPER_3(set_cp15, void, env, i32, i32)
-DEF_HELPER_2(get_cp15, i32, env, i32)
-
-DEF_HELPER_3(set_cp, void, env, i32, i32)
-DEF_HELPER_2(get_cp, i32, env, i32)
-
-DEF_HELPER_2(get_r13_banked, i32, env, i32)
-DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
-
-DEF_HELPER_1(get_user_reg, i32, i32)
-DEF_HELPER_2(set_user_reg, void, i32, i32)
-
-DEF_HELPER_1(vfp_get_fpscr, i32, env)
-DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
-
-DEF_HELPER_3(vfp_adds, f32, f32, f32, env)
-DEF_HELPER_3(vfp_addd, f64, f64, f64, env)
-DEF_HELPER_3(vfp_subs, f32, f32, f32, env)
-DEF_HELPER_3(vfp_subd, f64, f64, f64, env)
-DEF_HELPER_3(vfp_muls, f32, f32, f32, env)
-DEF_HELPER_3(vfp_muld, f64, f64, f64, env)
-DEF_HELPER_3(vfp_divs, f32, f32, f32, env)
-DEF_HELPER_3(vfp_divd, f64, f64, f64, env)
-DEF_HELPER_1(vfp_negs, f32, f32)
-DEF_HELPER_1(vfp_negd, f64, f64)
-DEF_HELPER_1(vfp_abss, f32, f32)
-DEF_HELPER_1(vfp_absd, f64, f64)
-DEF_HELPER_2(vfp_sqrts, f32, f32, env)
-DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
-DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
-DEF_HELPER_3(vfp_cmpd, void, f64, f64, env)
-DEF_HELPER_3(vfp_cmpes, void, f32, f32, env)
-DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
-
-DEF_HELPER_2(vfp_fcvtds, f64, f32, env)
-DEF_HELPER_2(vfp_fcvtsd, f32, f64, env)
-
-DEF_HELPER_2(vfp_uitos, f32, i32, env)
-DEF_HELPER_2(vfp_uitod, f64, i32, env)
-DEF_HELPER_2(vfp_sitos, f32, i32, env)
-DEF_HELPER_2(vfp_sitod, f64, i32, env)
-
-DEF_HELPER_2(vfp_touis, i32, f32, env)
-DEF_HELPER_2(vfp_touid, i32, f64, env)
-DEF_HELPER_2(vfp_touizs, i32, f32, env)
-DEF_HELPER_2(vfp_touizd, i32, f64, env)
-DEF_HELPER_2(vfp_tosis, i32, f32, env)
-DEF_HELPER_2(vfp_tosid, i32, f64, env)
-DEF_HELPER_2(vfp_tosizs, i32, f32, env)
-DEF_HELPER_2(vfp_tosizd, i32, f64, env)
-
-DEF_HELPER_3(vfp_toshs, i32, f32, i32, env)
-DEF_HELPER_3(vfp_tosls, i32, f32, i32, env)
-DEF_HELPER_3(vfp_touhs, i32, f32, i32, env)
-DEF_HELPER_3(vfp_touls, i32, f32, i32, env)
-DEF_HELPER_3(vfp_toshd, i64, f64, i32, env)
-DEF_HELPER_3(vfp_tosld, i64, f64, i32, env)
-DEF_HELPER_3(vfp_touhd, i64, f64, i32, env)
-DEF_HELPER_3(vfp_tould, i64, f64, i32, env)
-DEF_HELPER_3(vfp_shtos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_sltos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_uhtos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_ultos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_shtod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_sltod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_uhtod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_ultod, f64, i64, i32, env)
-
-DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
-DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
-DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
-DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
-
-DEF_HELPER_3(recps_f32, f32, f32, f32, env)
-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
-DEF_HELPER_2(recpe_f32, f32, f32, env)
-DEF_HELPER_2(rsqrte_f32, f32, f32, env)
-DEF_HELPER_2(recpe_u32, i32, i32, env)
-DEF_HELPER_2(rsqrte_u32, i32, i32, env)
-DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32)
-
-DEF_HELPER_2(add_cc, i32, i32, i32)
-DEF_HELPER_2(adc_cc, i32, i32, i32)
-DEF_HELPER_2(sub_cc, i32, i32, i32)
-DEF_HELPER_2(sbc_cc, i32, i32, i32)
-
-DEF_HELPER_2(shl, i32, i32, i32)
-DEF_HELPER_2(shr, i32, i32, i32)
-DEF_HELPER_2(sar, i32, i32, i32)
-DEF_HELPER_2(shl_cc, i32, i32, i32)
-DEF_HELPER_2(shr_cc, i32, i32, i32)
-DEF_HELPER_2(sar_cc, i32, i32, i32)
-DEF_HELPER_2(ror_cc, i32, i32, i32)
-
-/* neon_helper.c */
-DEF_HELPER_2(neon_qadd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qsub_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qadd_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qadd_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qsub_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qsub_s64, i64, i64, i64)
-
-DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_hadd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_hadd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_hadd_s32, s32, s32, s32)
-DEF_HELPER_2(neon_hadd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_rhadd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_rhadd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_rhadd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_rhadd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_rhadd_s32, s32, s32, s32)
-DEF_HELPER_2(neon_rhadd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_hsub_s8, i32, i32, i32)
-DEF_HELPER_2(neon_hsub_u8, i32, i32, i32)
-DEF_HELPER_2(neon_hsub_s16, i32, i32, i32)
-DEF_HELPER_2(neon_hsub_u16, i32, i32, i32)
-DEF_HELPER_2(neon_hsub_s32, s32, s32, s32)
-DEF_HELPER_2(neon_hsub_u32, i32, i32, i32)
-
-DEF_HELPER_2(neon_cgt_u8, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_s8, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_u16, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_s16, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_u32, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_s32, i32, i32, i32)
-DEF_HELPER_2(neon_cge_u8, i32, i32, i32)
-DEF_HELPER_2(neon_cge_s8, i32, i32, i32)
-DEF_HELPER_2(neon_cge_u16, i32, i32, i32)
-DEF_HELPER_2(neon_cge_s16, i32, i32, i32)
-DEF_HELPER_2(neon_cge_u32, i32, i32, i32)
-DEF_HELPER_2(neon_cge_s32, i32, i32, i32)
-
-DEF_HELPER_2(neon_min_u8, i32, i32, i32)
-DEF_HELPER_2(neon_min_s8, i32, i32, i32)
-DEF_HELPER_2(neon_min_u16, i32, i32, i32)
-DEF_HELPER_2(neon_min_s16, i32, i32, i32)
-DEF_HELPER_2(neon_min_u32, i32, i32, i32)
-DEF_HELPER_2(neon_min_s32, i32, i32, i32)
-DEF_HELPER_2(neon_max_u8, i32, i32, i32)
-DEF_HELPER_2(neon_max_s8, i32, i32, i32)
-DEF_HELPER_2(neon_max_u16, i32, i32, i32)
-DEF_HELPER_2(neon_max_s16, i32, i32, i32)
-DEF_HELPER_2(neon_max_u32, i32, i32, i32)
-DEF_HELPER_2(neon_max_s32, i32, i32, i32)
-DEF_HELPER_2(neon_pmin_u8, i32, i32, i32)
-DEF_HELPER_2(neon_pmin_s8, i32, i32, i32)
-DEF_HELPER_2(neon_pmin_u16, i32, i32, i32)
-DEF_HELPER_2(neon_pmin_s16, i32, i32, i32)
-DEF_HELPER_2(neon_pmax_u8, i32, i32, i32)
-DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
-DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
-DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
-
-DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
-
-DEF_HELPER_2(neon_shl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_shl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_shl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_shl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_shl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_shl_s64, i64, i64, i64)
-DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_rshl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_rshl_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qshl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qshl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qshl_s64, i64, i64, i64)
-DEF_HELPER_2(neon_qshlu_s8, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s16, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s32, i32, i32, i32);
-DEF_HELPER_2(neon_qshlu_s64, i64, i64, i64);
-DEF_HELPER_2(neon_qrshl_u8, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s8, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u16, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u32, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qrshl_u64, i64, i64, i64)
-DEF_HELPER_2(neon_qrshl_s64, i64, i64, i64)
-
-DEF_HELPER_2(neon_add_u8, i32, i32, i32)
-DEF_HELPER_2(neon_add_u16, i32, i32, i32)
-DEF_HELPER_2(neon_padd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_padd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_sub_u8, i32, i32, i32)
-DEF_HELPER_2(neon_sub_u16, i32, i32, i32)
-DEF_HELPER_2(neon_mul_u8, i32, i32, i32)
-DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
-DEF_HELPER_2(neon_mul_p8, i32, i32, i32)
-DEF_HELPER_2(neon_mull_p8, i64, i32, i32)
-
-DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
-DEF_HELPER_2(neon_tst_u16, i32, i32, i32)
-DEF_HELPER_2(neon_tst_u32, i32, i32, i32)
-DEF_HELPER_2(neon_ceq_u8, i32, i32, i32)
-DEF_HELPER_2(neon_ceq_u16, i32, i32, i32)
-DEF_HELPER_2(neon_ceq_u32, i32, i32, i32)
-
-DEF_HELPER_1(neon_abs_s8, i32, i32)
-DEF_HELPER_1(neon_abs_s16, i32, i32)
-DEF_HELPER_1(neon_clz_u8, i32, i32)
-DEF_HELPER_1(neon_clz_u16, i32, i32)
-DEF_HELPER_1(neon_cls_s8, i32, i32)
-DEF_HELPER_1(neon_cls_s16, i32, i32)
-DEF_HELPER_1(neon_cls_s32, i32, i32)
-DEF_HELPER_1(neon_cnt_u8, i32, i32)
-
-DEF_HELPER_2(neon_qdmulh_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qrdmulh_s16, i32, i32, i32)
-DEF_HELPER_2(neon_qdmulh_s32, i32, i32, i32)
-DEF_HELPER_2(neon_qrdmulh_s32, i32, i32, i32)
-
-DEF_HELPER_1(neon_narrow_u8, i32, i64)
-DEF_HELPER_1(neon_narrow_u16, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat8, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u8, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s8, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat16, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u16, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s16, i32, i64)
-DEF_HELPER_1(neon_unarrow_sat32, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_u32, i32, i64)
-DEF_HELPER_1(neon_narrow_sat_s32, i32, i64)
-DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
-DEF_HELPER_1(neon_narrow_high_u16, i32, i64)
-DEF_HELPER_1(neon_narrow_round_high_u8, i32, i64)
-DEF_HELPER_1(neon_narrow_round_high_u16, i32, i64)
-DEF_HELPER_1(neon_widen_u8, i64, i32)
-DEF_HELPER_1(neon_widen_s8, i64, i32)
-DEF_HELPER_1(neon_widen_u16, i64, i32)
-DEF_HELPER_1(neon_widen_s16, i64, i32)
-
-DEF_HELPER_2(neon_addl_u16, i64, i64, i64)
-DEF_HELPER_2(neon_addl_u32, i64, i64, i64)
-DEF_HELPER_2(neon_paddl_u16, i64, i64, i64)
-DEF_HELPER_2(neon_paddl_u32, i64, i64, i64)
-DEF_HELPER_2(neon_subl_u16, i64, i64, i64)
-DEF_HELPER_2(neon_subl_u32, i64, i64, i64)
-DEF_HELPER_2(neon_addl_saturate_s32, i64, i64, i64)
-DEF_HELPER_2(neon_addl_saturate_s64, i64, i64, i64)
-DEF_HELPER_2(neon_abdl_u16, i64, i32, i32)
-DEF_HELPER_2(neon_abdl_s16, i64, i32, i32)
-DEF_HELPER_2(neon_abdl_u32, i64, i32, i32)
-DEF_HELPER_2(neon_abdl_s32, i64, i32, i32)
-DEF_HELPER_2(neon_abdl_u64, i64, i32, i32)
-DEF_HELPER_2(neon_abdl_s64, i64, i32, i32)
-DEF_HELPER_2(neon_mull_u8, i64, i32, i32)
-DEF_HELPER_2(neon_mull_s8, i64, i32, i32)
-DEF_HELPER_2(neon_mull_u16, i64, i32, i32)
-DEF_HELPER_2(neon_mull_s16, i64, i32, i32)
-
-DEF_HELPER_1(neon_negl_u16, i64, i64)
-DEF_HELPER_1(neon_negl_u32, i64, i64)
-DEF_HELPER_1(neon_negl_u64, i64, i64)
-
-DEF_HELPER_1(neon_qabs_s8, i32, i32)
-DEF_HELPER_1(neon_qabs_s16, i32, i32)
-DEF_HELPER_1(neon_qabs_s32, i32, i32)
-DEF_HELPER_1(neon_qneg_s8, i32, i32)
-DEF_HELPER_1(neon_qneg_s16, i32, i32)
-DEF_HELPER_1(neon_qneg_s32, i32, i32)
-
-DEF_HELPER_2(neon_min_f32, i32, i32, i32)
-DEF_HELPER_2(neon_max_f32, i32, i32, i32)
-DEF_HELPER_2(neon_abd_f32, i32, i32, i32)
-DEF_HELPER_2(neon_add_f32, i32, i32, i32)
-DEF_HELPER_2(neon_sub_f32, i32, i32, i32)
-DEF_HELPER_2(neon_mul_f32, i32, i32, i32)
-DEF_HELPER_2(neon_ceq_f32, i32, i32, i32)
-DEF_HELPER_2(neon_cge_f32, i32, i32, i32)
-DEF_HELPER_2(neon_cgt_f32, i32, i32, i32)
-DEF_HELPER_2(neon_acge_f32, i32, i32, i32)
-DEF_HELPER_2(neon_acgt_f32, i32, i32, i32)
-
-/* iwmmxt_helper.c */
-DEF_HELPER_2(iwmmxt_maddsq, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_madduq, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_sadb, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_sadw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_mulslw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_mulshw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_mululw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_muluhw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_macsw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_macuw, i64, i64, i64)
-DEF_HELPER_1(iwmmxt_setpsr_nz, i32, i64)
-
-#define DEF_IWMMXT_HELPER_SIZE(name) \
-DEF_HELPER_2(iwmmxt_##name##b, i64, i64, i64) \
-DEF_HELPER_2(iwmmxt_##name##w, i64, i64, i64) \
-DEF_HELPER_2(iwmmxt_##name##l, i64, i64, i64) \
-
-DEF_IWMMXT_HELPER_SIZE(unpackl)
-DEF_IWMMXT_HELPER_SIZE(unpackh)
-
-DEF_HELPER_1(iwmmxt_unpacklub, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackluw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklul, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhub, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhuw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhul, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsb, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpacklsl, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsb, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsw, i64, i64)
-DEF_HELPER_1(iwmmxt_unpackhsl, i64, i64)
-
-DEF_IWMMXT_HELPER_SIZE(cmpeq)
-DEF_IWMMXT_HELPER_SIZE(cmpgtu)
-DEF_IWMMXT_HELPER_SIZE(cmpgts)
-
-DEF_IWMMXT_HELPER_SIZE(mins)
-DEF_IWMMXT_HELPER_SIZE(minu)
-DEF_IWMMXT_HELPER_SIZE(maxs)
-DEF_IWMMXT_HELPER_SIZE(maxu)
-
-DEF_IWMMXT_HELPER_SIZE(subn)
-DEF_IWMMXT_HELPER_SIZE(addn)
-DEF_IWMMXT_HELPER_SIZE(subu)
-DEF_IWMMXT_HELPER_SIZE(addu)
-DEF_IWMMXT_HELPER_SIZE(subs)
-DEF_IWMMXT_HELPER_SIZE(adds)
-
-DEF_HELPER_2(iwmmxt_avgb0, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgb1, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgw0, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_avgw1, i64, i64, i64)
-
-DEF_HELPER_2(iwmmxt_msadb, i64, i64, i64)
-
-DEF_HELPER_3(iwmmxt_align, i64, i64, i64, i32)
-DEF_HELPER_4(iwmmxt_insr, i64, i64, i32, i32, i32)
-
-DEF_HELPER_1(iwmmxt_bcstb, i64, i32)
-DEF_HELPER_1(iwmmxt_bcstw, i64, i32)
-DEF_HELPER_1(iwmmxt_bcstl, i64, i32)
-
-DEF_HELPER_1(iwmmxt_addcb, i64, i64)
-DEF_HELPER_1(iwmmxt_addcw, i64, i64)
-DEF_HELPER_1(iwmmxt_addcl, i64, i64)
-
-DEF_HELPER_1(iwmmxt_msbb, i32, i64)
-DEF_HELPER_1(iwmmxt_msbw, i32, i64)
-DEF_HELPER_1(iwmmxt_msbl, i32, i64)
-
-DEF_HELPER_2(iwmmxt_srlw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_srll, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_srlq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sllw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_slll, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sllq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sraw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sral, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_sraq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorw, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorl, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_rorq, i64, i64, i32)
-DEF_HELPER_2(iwmmxt_shufh, i64, i64, i32)
-
-DEF_HELPER_2(iwmmxt_packuw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packul, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packuq, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsw, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsl, i64, i64, i64)
-DEF_HELPER_2(iwmmxt_packsq, i64, i64, i64)
-
-DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
-DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
-DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
-
-DEF_HELPER_2(set_teecr, void, env, i32)
-
-DEF_HELPER_2(neon_unzip8, void, i32, i32)
-DEF_HELPER_2(neon_unzip16, void, i32, i32)
-DEF_HELPER_2(neon_qunzip8, void, i32, i32)
-DEF_HELPER_2(neon_qunzip16, void, i32, i32)
-DEF_HELPER_2(neon_qunzip32, void, i32, i32)
-DEF_HELPER_2(neon_zip8, void, i32, i32)
-DEF_HELPER_2(neon_zip16, void, i32, i32)
-DEF_HELPER_2(neon_qzip8, void, i32, i32)
-DEF_HELPER_2(neon_qzip16, void, i32, i32)
-DEF_HELPER_2(neon_qzip32, void, i32, i32)
-
-#include "def-helper.h"
diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c
index 3941f1f..ebe6eb9 100644
--- a/target-arm/iwmmxt_helper.c
+++ b/target-arm/iwmmxt_helper.c
@@ -24,7 +24,7 @@
 
 #include "cpu.h"
 #include "exec.h"
-#include "helpers.h"
+#include "helper.h"
 
 /* iwMMXt macros extracted from GNU gdb.  */
 
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 7df925a..f5b173a 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -11,7 +11,7 @@
 
 #include "cpu.h"
 #include "exec.h"
-#include "helpers.h"
+#include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 3de2610..ee7286b 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -17,7 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "exec.h"
-#include "helpers.h"
+#include "helper.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6190028..fc9ff8d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -30,9 +30,9 @@
 #include "tcg-op.h"
 #include "qemu-log.h"
 
-#include "helpers.h"
+#include "helper.h"
 #define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
 
 #define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
 #define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
@@ -129,7 +129,7 @@ void arm_translate_init(void)
 #endif
 
 #define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
 }
 
 static inline TCGv load_cpu_offset(int offset)
commit 685ff50f698f11dec8e9e193e8bc86b051a8cf26
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Apr 13 14:42:00 2011 +0300

    libcacard: fix opposite usage of isspace
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Tested-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 71f2ba3..baada52 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -955,7 +955,7 @@ count_tokens(const char *str, char token, char token_end)
 static const char *
 strip(const char *str)
 {
-    for (; *str && !isspace(*str); str++) {
+    for (; *str && isspace(*str); str++) {
     }
     return str;
 }
@@ -963,7 +963,7 @@ strip(const char *str)
 static const char *
 find_blank(const char *str)
 {
-    for (; *str && isspace(*str); str++) {
+    for (; *str && !isspace(*str); str++) {
     }
     return str;
 }
commit 6a385343e42c500f8404ecf9365ff63f4c942057
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    target-mips: clear softfpu exception state for comparison instructions
    
    MIPS FPU instructions should start with a clean softfpu status. This
    is done for the most instructions, but not for comparison ones.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index b35a6d2..8cba535 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2874,7 +2874,9 @@ uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
 #define FOP_COND_D(op, cond)                                   \
 void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
 {                                                              \
-    int c = cond;                                              \
+    int c;                                                     \
+    set_float_exception_flags(0, &env->active_fpu.fp_status);  \
+    c = cond;                                                  \
     update_fcr31();                                            \
     if (c)                                                     \
         SET_FP_COND(cc, env->active_fpu);                      \
@@ -2884,6 +2886,7 @@ void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
 void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
 {                                                              \
     int c;                                                     \
+    set_float_exception_flags(0, &env->active_fpu.fp_status);  \
     fdt0 = float64_abs(fdt0);                                  \
     fdt1 = float64_abs(fdt1);                                  \
     c = cond;                                                  \
@@ -2918,7 +2921,9 @@ FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || fl
 #define FOP_COND_S(op, cond)                                   \
 void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
 {                                                              \
-    int c = cond;                                              \
+    int c;                                                     \
+    set_float_exception_flags(0, &env->active_fpu.fp_status);  \
+    c = cond;                                                  \
     update_fcr31();                                            \
     if (c)                                                     \
         SET_FP_COND(cc, env->active_fpu);                      \
@@ -2928,6 +2933,7 @@ void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
 void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
 {                                                              \
     int c;                                                     \
+    set_float_exception_flags(0, &env->active_fpu.fp_status);  \
     fst0 = float32_abs(fst0);                                  \
     fst1 = float32_abs(fst1);                                  \
     c = cond;                                                  \
@@ -2962,13 +2968,15 @@ FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || fl
 #define FOP_COND_PS(op, condl, condh)                           \
 void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
 {                                                               \
-    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                          \
-    uint32_t fsth0 = fdt0 >> 32;                                \
-    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                          \
-    uint32_t fsth1 = fdt1 >> 32;                                \
-    int cl = condl;                                             \
-    int ch = condh;                                             \
-                                                                \
+    uint32_t fst0, fsth0, fst1, fsth1;                          \
+    int ch, cl;                                                 \
+    set_float_exception_flags(0, &env->active_fpu.fp_status);   \
+    fst0 = fdt0 & 0XFFFFFFFF;                                   \
+    fsth0 = fdt0 >> 32;                                         \
+    fst1 = fdt1 & 0XFFFFFFFF;                                   \
+    fsth1 = fdt1 >> 32;                                         \
+    cl = condl;                                                 \
+    ch = condh;                                                 \
     update_fcr31();                                             \
     if (cl)                                                     \
         SET_FP_COND(cc, env->active_fpu);                       \
@@ -2981,13 +2989,14 @@ void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
 }                                                               \
 void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
 {                                                               \
-    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
-    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
-    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
-    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
-    int cl = condl;                                             \
-    int ch = condh;                                             \
-                                                                \
+    uint32_t fst0, fsth0, fst1, fsth1;                          \
+    int ch, cl;                                                 \
+    fst0 = float32_abs(fdt0 & 0XFFFFFFFF);                      \
+    fsth0 = float32_abs(fdt0 >> 32);                            \
+    fst1 = float32_abs(fdt1 & 0XFFFFFFFF);                      \
+    fsth1 = float32_abs(fdt1 >> 32);                            \
+    cl = condl;                                                 \
+    ch = condh;                                                 \
     update_fcr31();                                             \
     if (cl)                                                     \
         SET_FP_COND(cc, env->active_fpu);                       \
commit 30a00bc142796f6d436b0b79f01757afb1e4c1e7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    target-mips: fix c.ps.* instructions
    
    Contrary to cabs.ps.* instructions, c.ps.* should not compare the absolute
    value of the operand, but directly the operands.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 0a62361..b35a6d2 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2962,10 +2962,10 @@ FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || fl
 #define FOP_COND_PS(op, condl, condh)                           \
 void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
 {                                                               \
-    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
-    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
-    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
-    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
+    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                          \
+    uint32_t fsth0 = fdt0 >> 32;                                \
+    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                          \
+    uint32_t fsth1 = fdt1 >> 32;                                \
     int cl = condl;                                             \
     int ch = condh;                                             \
                                                                 \
commit 353ebb7ac22f2866ac3680a3340aa21185c50407
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    target-mips: don't hardcode softfloat exception bits
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index abcb6eb..0a62361 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2077,22 +2077,27 @@ void helper_ctc1 (target_ulong arg1, uint32_t reg)
         helper_raise_exception(EXCP_FPE);
 }
 
-static inline char ieee_ex_to_mips(char xcpt)
+static inline int ieee_ex_to_mips(int xcpt)
 {
-    return (xcpt & float_flag_inexact) >> 5 |
-           (xcpt & float_flag_underflow) >> 3 |
-           (xcpt & float_flag_overflow) >> 1 |
-           (xcpt & float_flag_divbyzero) << 1 |
-           (xcpt & float_flag_invalid) << 4;
-}
-
-static inline char mips_ex_to_ieee(char xcpt)
-{
-    return (xcpt & FP_INEXACT) << 5 |
-           (xcpt & FP_UNDERFLOW) << 3 |
-           (xcpt & FP_OVERFLOW) << 1 |
-           (xcpt & FP_DIV0) >> 1 |
-           (xcpt & FP_INVALID) >> 4;
+    int ret = 0;
+    if (xcpt) {
+        if (xcpt & float_flag_invalid) {
+            ret |= FP_INVALID;
+        }
+        if (xcpt & float_flag_overflow) {
+            ret |= FP_OVERFLOW;
+        }
+        if (xcpt & float_flag_underflow) {
+            ret |= FP_UNDERFLOW;
+        }
+        if (xcpt & float_flag_divbyzero) {
+            ret |= FP_DIV0;
+        }
+        if (xcpt & float_flag_inexact) {
+            ret |= FP_INEXACT;
+        }
+    }
+    return ret;
 }
 
 static inline void update_fcr31(void)
commit 06a0e6b104718803bceecbb5efd4125bcf71d8c7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    target-mips: simplify FP comparisons
    
    As the softfloat comparison functions already test for NaN, there is no
    need to always call the float*_unordered*() functions.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 31a19ba..abcb6eb 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2893,21 +2893,21 @@ void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
  * but float64_unordered_quiet() is still called. */
 FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
 FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(eq,  !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(eq,  float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(olt, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ole, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
  * but float64_unordered() is still called. */
 FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
 FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(seq, !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(lt,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(lt,  float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(le,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(le,  float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
 
 #define FOP_COND_S(op, cond)                                   \
@@ -2937,21 +2937,21 @@ void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
  * but float32_unordered_quiet() is still called. */
 FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
 FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
  * but float32_unordered() is still called. */
 FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
 FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
 
 #define FOP_COND_PS(op, condl, condh)                           \
@@ -3000,33 +3000,33 @@ FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status
                  (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
 FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
  * but float32_unordered() is still called. */
 FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
                  (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
 FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
commit 019702c8156ee442378a520b733d823c0c62072b
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    target-ppc: fix SPE comparison functions
    
    efstst*() functions are fast SPE funtions which do not take into account
    special values (infinites, NaN, etc.), while efscmp*() functions are
    IEEE754 compliant.
    
    Given that float32_*() functions are IEEE754 compliant, the efscmp*()
    functions are correctly implemented, while efstst*() are not. This
    patch reverse the implementation of this two groups of functions and
    fix the comments. It also use float32_eq() instead of float32_eq_quiet()
    as qNaNs should not be ignored.
    
    Cc: Alexander Graf <agraf at suse.de>
    Cc: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 898ffd0..28d40ac 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3343,7 +3343,7 @@ HELPER_SPE_VECTOR_ARITH(fsmul);
 HELPER_SPE_VECTOR_ARITH(fsdiv);
 
 /* Single-precision floating-point comparisons */
-static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
 {
     CPU_FloatU u1, u2;
     u1.l = op1;
@@ -3351,7 +3351,7 @@ static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
     return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
 }
 
-static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
 {
     CPU_FloatU u1, u2;
     u1.l = op1;
@@ -3359,30 +3359,30 @@ static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
     return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
 }
 
-static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
+static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
 {
     CPU_FloatU u1, u2;
     u1.l = op1;
     u2.l = op2;
-    return float32_eq_quiet(u1.f, u2.f, &env->vec_status) ? 4 : 0;
+    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
 }
 
-static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
+static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
 {
-    /* XXX: TODO: test special values (NaN, infinites, ...) */
-    return efststlt(op1, op2);
+    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+    return efscmplt(op1, op2);
 }
 
-static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
+static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
 {
-    /* XXX: TODO: test special values (NaN, infinites, ...) */
-    return efststgt(op1, op2);
+    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+    return efscmpgt(op1, op2);
 }
 
-static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
+static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
 {
-    /* XXX: TODO: test special values (NaN, infinites, ...) */
-    return efststeq(op1, op2);
+    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
+    return efscmpeq(op1, op2);
 }
 
 #define HELPER_SINGLE_SPE_CMP(name)                                           \
commit f5a64251f2db2271970a1f4b7f8176d4de4dec91
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:30 2011 +0200

    softfloat: improve description of comparison functions
    
    Make clear for all comparison functions which ones trigger an exception
    for all NaNs, and which one only for sNaNs.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index efd718b..6ce0b61 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2338,9 +2338,9 @@ int float32_eq( float32 a, float32 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise.  The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| or equal to the corresponding value `b', and 0 otherwise.  The invalid
+| exception is raised if either operand is a NaN.  The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float32_le( float32 a, float32 b STATUS_PARAM )
@@ -2367,8 +2367,9 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float32_lt( float32 a, float32 b STATUS_PARAM )
@@ -2395,8 +2396,9 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise.  The comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| be compared, and 0 otherwise.  The invalid exception is raised if either
+| operand is a NaN.  The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float32_unordered( float32 a, float32 b STATUS_PARAM )
@@ -2415,8 +2417,9 @@ int float32_unordered( float32 a, float32 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+| exception.  The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
@@ -3602,9 +3605,9 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is less than or
-| equal to the corresponding value `b', and 0 otherwise.  The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| equal to the corresponding value `b', and 0 otherwise.  The invalid
+| exception is raised if either operand is a NaN.  The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float64_le( float64 a, float64 b STATUS_PARAM )
@@ -3631,8 +3634,9 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float64_lt( float64 a, float64 b STATUS_PARAM )
@@ -3659,8 +3663,9 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise.  The comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| be compared, and 0 otherwise.  The invalid exception is raised if either
+| operand is a NaN.  The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float64_unordered( float64 a, float64 b STATUS_PARAM )
@@ -3679,8 +3684,9 @@ int float64_unordered( float64 a, float64 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+| exception.The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
@@ -4614,8 +4620,9 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is
 | less than or equal to the corresponding value `b', and 0 otherwise.  The
-| comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
+| invalid exception is raised if either operand is a NaN.  The comparison is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
@@ -4646,9 +4653,9 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is
-| less than the corresponding value `b', and 0 otherwise.  The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| less than the corresponding value `b', and 0 otherwise.  The invalid
+| exception is raised if either operand is a NaN.  The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
@@ -4679,8 +4686,9 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point values `a' and `b'
-| cannot be compared, and 0 otherwise.  The comparison is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| cannot be compared, and 0 otherwise.  The invalid exception is raised if
+| either operand is a NaN.   The comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
 {
@@ -4697,9 +4705,9 @@ int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is
-| equal to the corresponding value `b', and 0 otherwise.  The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
+| cause an exception.  The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
@@ -5776,9 +5784,9 @@ int float128_eq( float128 a, float128 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise.  The comparison
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| or equal to the corresponding value `b', and 0 otherwise.  The invalid
+| exception is raised if either operand is a NaN.  The comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float128_le( float128 a, float128 b STATUS_PARAM )
@@ -5809,8 +5817,9 @@ int float128_le( float128 a, float128 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float128_lt( float128 a, float128 b STATUS_PARAM )
@@ -5841,8 +5850,9 @@ int float128_lt( float128 a, float128 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise.  The comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| be compared, and 0 otherwise.  The invalid exception is raised if either
+| operand is a NaN. The comparison is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float128_unordered( float128 a, float128 b STATUS_PARAM )
@@ -5860,8 +5870,9 @@ int float128_unordered( float128 a, float128 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+| exception.  The comparison is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
 int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
commit b689362d14e7b5689c6e006f962268764ed5df64
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat: move float*_eq and float*_eq_quiet
    
    I am not a big fan of code moving, but having the signaling version in
    the middle of quiet versions and vice versa doesn't make the code easy
    to read.
    
    This patch is a simple code move, basically swapping locations of
    float*_eq and float*_eq_quiet.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 2e02940..efd718b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2314,26 +2314,26 @@ float32 float32_log2( float32 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
+| the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  Otherwise, the comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
+int float32_eq( float32 a, float32 b STATUS_PARAM )
 {
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
-        }
+        float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
-    return ( float32_val(a) == float32_val(b) ) ||
-            ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
-
+    av = float32_val(a);
+    bv = float32_val(b);
+    return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
 }
 
 /*----------------------------------------------------------------------------
@@ -2412,29 +2412,28 @@ int float32_unordered( float32 a, float32 b STATUS_PARAM )
     }
     return 0;
 }
+
 /*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The invalid exception is
-| raised if either operand is a NaN.  Otherwise, the comparison is performed
+| the corresponding value `b', and 0 otherwise.  The comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float32_eq( float32 a, float32 b STATUS_PARAM )
+int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
 {
-    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        float_raise( float_flag_invalid STATUS_VAR);
+        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
         return 0;
     }
-    av = float32_val(a);
-    bv = float32_val(b);
-    return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
-
+    return ( float32_val(a) == float32_val(b) ) ||
+            ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
 }
 
 /*----------------------------------------------------------------------------
@@ -3578,11 +3577,12 @@ float64 float64_log2( float64 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise.  The comparison is performed
+| corresponding value `b', and 0 otherwise.  The invalid exception is raised
+| if either operand is a NaN.  Otherwise, the comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
+int float64_eq( float64 a, float64 b STATUS_PARAM )
 {
     uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3591,9 +3591,7 @@ int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
-        }
+        float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
     av = float64_val(a);
@@ -3681,12 +3679,11 @@ int float64_unordered( float64 a, float64 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise.  The invalid exception is raised
-| if either operand is a NaN.  Otherwise, the comparison is performed
+| corresponding value `b', and 0 otherwise.  The comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float64_eq( float64 a, float64 b STATUS_PARAM )
+int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
 {
     uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3695,7 +3692,9 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        float_raise( float_flag_invalid STATUS_VAR);
+        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
         return 0;
     }
     av = float64_val(a);
@@ -4586,13 +4585,13 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is
-| equal to the corresponding value `b', and 0 otherwise.  The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
+| Returns 1 if the extended double-precision floating-point value `a' is equal
+| to the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  Otherwise, the comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -4600,10 +4599,7 @@ int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
-        }
+        float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
     return
@@ -4700,13 +4696,13 @@ int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is equal
-| to the corresponding value `b', and 0 otherwise.  The invalid exception is
-| raised if either operand is a NaN.  Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+| Returns 1 if the extended double-precision floating-point value `a' is
+| equal to the corresponding value `b', and 0 otherwise.  The comparison is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -4714,7 +4710,10 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        float_raise( float_flag_invalid STATUS_VAR);
+        if (    floatx80_is_signaling_nan( a )
+             || floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
         return 0;
     }
     return
@@ -5750,11 +5749,12 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The comparison is performed
+| the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  Otherwise, the comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
+int float128_eq( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5762,10 +5762,7 @@ int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        if (    float128_is_signaling_nan( a )
-             || float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
-        }
+        float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
     return
@@ -5863,12 +5860,11 @@ int float128_unordered( float128 a, float128 b STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise.  The invalid exception is
-| raised if either operand is a NaN.  Otherwise, the comparison is performed
+| the corresponding value `b', and 0 otherwise.  The comparison is performed
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float128_eq( float128 a, float128 b STATUS_PARAM )
+int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5876,7 +5872,10 @@ int float128_eq( float128 a, float128 b STATUS_PARAM )
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        float_raise( float_flag_invalid STATUS_VAR);
+        if (    float128_is_signaling_nan( a )
+             || float128_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
         return 0;
     }
     return
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index b9440b2..340f0a9 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -320,11 +320,11 @@ float32 float32_rem( float32, float32 STATUS_PARAM );
 float32 float32_sqrt( float32 STATUS_PARAM );
 float32 float32_exp2( float32 STATUS_PARAM );
 float32 float32_log2( float32 STATUS_PARAM );
-int float32_eq_quiet( float32, float32 STATUS_PARAM );
+int float32_eq( float32, float32 STATUS_PARAM );
 int float32_le( float32, float32 STATUS_PARAM );
 int float32_lt( float32, float32 STATUS_PARAM );
 int float32_unordered( float32, float32 STATUS_PARAM );
-int float32_eq( float32, float32 STATUS_PARAM );
+int float32_eq_quiet( float32, float32 STATUS_PARAM );
 int float32_le_quiet( float32, float32 STATUS_PARAM );
 int float32_lt_quiet( float32, float32 STATUS_PARAM );
 int float32_unordered_quiet( float32, float32 STATUS_PARAM );
@@ -436,11 +436,11 @@ float64 float64_div( float64, float64 STATUS_PARAM );
 float64 float64_rem( float64, float64 STATUS_PARAM );
 float64 float64_sqrt( float64 STATUS_PARAM );
 float64 float64_log2( float64 STATUS_PARAM );
-int float64_eq_quiet( float64, float64 STATUS_PARAM );
+int float64_eq( float64, float64 STATUS_PARAM );
 int float64_le( float64, float64 STATUS_PARAM );
 int float64_lt( float64, float64 STATUS_PARAM );
 int float64_unordered( float64, float64 STATUS_PARAM );
-int float64_eq( float64, float64 STATUS_PARAM );
+int float64_eq_quiet( float64, float64 STATUS_PARAM );
 int float64_le_quiet( float64, float64 STATUS_PARAM );
 int float64_lt_quiet( float64, float64 STATUS_PARAM );
 int float64_unordered_quiet( float64, float64 STATUS_PARAM );
@@ -539,11 +539,11 @@ floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
-int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
@@ -624,11 +624,11 @@ float128 float128_mul( float128, float128 STATUS_PARAM );
 float128 float128_div( float128, float128 STATUS_PARAM );
 float128 float128_rem( float128, float128 STATUS_PARAM );
 float128 float128_sqrt( float128 STATUS_PARAM );
-int float128_eq_quiet( float128, float128 STATUS_PARAM );
+int float128_eq( float128, float128 STATUS_PARAM );
 int float128_le( float128, float128 STATUS_PARAM );
 int float128_lt( float128, float128 STATUS_PARAM );
 int float128_unordered( float128, float128 STATUS_PARAM );
-int float128_eq( float128, float128 STATUS_PARAM );
+int float128_eq_quiet( float128, float128 STATUS_PARAM );
 int float128_le_quiet( float128, float128 STATUS_PARAM );
 int float128_lt_quiet( float128, float128 STATUS_PARAM );
 int float128_unordered_quiet( float128, float128 STATUS_PARAM );
commit 2657d0ff8f71cc5c084ee958d0087a5313099e74
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat: rename float*_eq_signaling() into float*_eq()
    
    float*_eq_signaling functions have a different semantics than other
    comparison functions. Fix that by renaming float*_quiet_signaling() into
    float*_eq().
    
    Note that it is purely mechanical, and the behaviour should be unchanged.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 0c7f48b..ea7a15e 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -222,7 +222,7 @@ INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
@@ -333,7 +333,7 @@ INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
@@ -440,7 +440,7 @@ INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 492ef36..2e02940 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2419,7 +2419,7 @@ int float32_unordered( float32 a, float32 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
+int float32_eq( float32 a, float32 b STATUS_PARAM )
 {
     uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
@@ -3686,7 +3686,7 @@ int float64_unordered( float64 a, float64 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
+int float64_eq( float64 a, float64 b STATUS_PARAM )
 {
     uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
@@ -4706,7 +4706,7 @@ int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -5868,7 +5868,7 @@ int float128_unordered( float128 a, float128 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
+int float128_eq( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 738a50c..b9440b2 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -324,7 +324,7 @@ int float32_eq_quiet( float32, float32 STATUS_PARAM );
 int float32_le( float32, float32 STATUS_PARAM );
 int float32_lt( float32, float32 STATUS_PARAM );
 int float32_unordered( float32, float32 STATUS_PARAM );
-int float32_eq_signaling( float32, float32 STATUS_PARAM );
+int float32_eq( float32, float32 STATUS_PARAM );
 int float32_le_quiet( float32, float32 STATUS_PARAM );
 int float32_lt_quiet( float32, float32 STATUS_PARAM );
 int float32_unordered_quiet( float32, float32 STATUS_PARAM );
@@ -440,7 +440,7 @@ int float64_eq_quiet( float64, float64 STATUS_PARAM );
 int float64_le( float64, float64 STATUS_PARAM );
 int float64_lt( float64, float64 STATUS_PARAM );
 int float64_unordered( float64, float64 STATUS_PARAM );
-int float64_eq_signaling( float64, float64 STATUS_PARAM );
+int float64_eq( float64, float64 STATUS_PARAM );
 int float64_le_quiet( float64, float64 STATUS_PARAM );
 int float64_lt_quiet( float64, float64 STATUS_PARAM );
 int float64_unordered_quiet( float64, float64 STATUS_PARAM );
@@ -543,7 +543,7 @@ int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
-int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
@@ -628,7 +628,7 @@ int float128_eq_quiet( float128, float128 STATUS_PARAM );
 int float128_le( float128, float128 STATUS_PARAM );
 int float128_lt( float128, float128 STATUS_PARAM );
 int float128_unordered( float128, float128 STATUS_PARAM );
-int float128_eq_signaling( float128, float128 STATUS_PARAM );
+int float128_eq( float128, float128 STATUS_PARAM );
 int float128_le_quiet( float128, float128 STATUS_PARAM );
 int float128_lt_quiet( float128, float128 STATUS_PARAM );
 int float128_unordered_quiet( float128, float128 STATUS_PARAM );
commit 211315fb5eb35c055e3134d58f2880d466bd5902
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat: rename float*_eq() into float*_eq_quiet()
    
    float*_eq functions have a different semantics than other comparison
    functions. Fix that by first renaming float*_quiet() into float*_eq_quiet().
    
    Note that it is purely mechanical, and the behaviour should be unchanged.
    That said it clearly highlight problems due to this different semantics,
    they are fixed later in this patch series.
    
    Cc: Alexander Graf <agraf at suse.de>
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 406e180..0c7f48b 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -210,7 +210,7 @@ INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
 }
 float32 float32_rem( float32, float32  STATUS_PARAM);
 float32 float32_sqrt( float32  STATUS_PARAM);
-INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq_quiet( float32 a, float32 b STATUS_PARAM)
 {
     return a == b;
 }
@@ -321,7 +321,7 @@ INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
 }
 float64 float64_rem( float64, float64 STATUS_PARAM );
 float64 float64_sqrt( float64 STATUS_PARAM );
-INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq_quiet( float64 a, float64 b STATUS_PARAM)
 {
     return a == b;
 }
@@ -428,7 +428,7 @@ INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
 }
 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a == b;
 }
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 11f6584..492ef36 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2318,7 +2318,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float32_eq( float32 a, float32 b STATUS_PARAM )
+int float32_eq_quiet( float32 a, float32 b STATUS_PARAM )
 {
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
@@ -3582,7 +3582,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float64_eq( float64 a, float64 b STATUS_PARAM )
+int float64_eq_quiet( float64 a, float64 b STATUS_PARAM )
 {
     uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
@@ -4592,7 +4592,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -5754,7 +5754,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-int float128_eq( float128 a, float128 b STATUS_PARAM )
+int float128_eq_quiet( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 55c0c1c..738a50c 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -320,7 +320,7 @@ float32 float32_rem( float32, float32 STATUS_PARAM );
 float32 float32_sqrt( float32 STATUS_PARAM );
 float32 float32_exp2( float32 STATUS_PARAM );
 float32 float32_log2( float32 STATUS_PARAM );
-int float32_eq( float32, float32 STATUS_PARAM );
+int float32_eq_quiet( float32, float32 STATUS_PARAM );
 int float32_le( float32, float32 STATUS_PARAM );
 int float32_lt( float32, float32 STATUS_PARAM );
 int float32_unordered( float32, float32 STATUS_PARAM );
@@ -436,7 +436,7 @@ float64 float64_div( float64, float64 STATUS_PARAM );
 float64 float64_rem( float64, float64 STATUS_PARAM );
 float64 float64_sqrt( float64 STATUS_PARAM );
 float64 float64_log2( float64 STATUS_PARAM );
-int float64_eq( float64, float64 STATUS_PARAM );
+int float64_eq_quiet( float64, float64 STATUS_PARAM );
 int float64_le( float64, float64 STATUS_PARAM );
 int float64_lt( float64, float64 STATUS_PARAM );
 int float64_unordered( float64, float64 STATUS_PARAM );
@@ -539,7 +539,7 @@ floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
 int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
@@ -624,7 +624,7 @@ float128 float128_mul( float128, float128 STATUS_PARAM );
 float128 float128_div( float128, float128 STATUS_PARAM );
 float128 float128_rem( float128, float128 STATUS_PARAM );
 float128 float128_sqrt( float128 STATUS_PARAM );
-int float128_eq( float128, float128 STATUS_PARAM );
+int float128_eq_quiet( float128, float128 STATUS_PARAM );
 int float128_le( float128, float128 STATUS_PARAM );
 int float128_lt( float128, float128 STATUS_PARAM );
 int float128_unordered( float128, float128 STATUS_PARAM );
diff --git a/linux-user/arm/nwfpe/fpa11_cprt.c b/linux-user/arm/nwfpe/fpa11_cprt.c
index be54e95..8011897 100644
--- a/linux-user/arm/nwfpe/fpa11_cprt.c
+++ b/linux-user/arm/nwfpe/fpa11_cprt.c
@@ -159,7 +159,7 @@ PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
    }
 
    /* test for equal condition */
-   if (floatx80_eq(Fn,Fm, &fpa11->fp_status))
+   if (floatx80_eq_quiet(Fn,Fm, &fpa11->fp_status))
    {
       flags |= CC_ZERO;
    }
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 36f4f6d..9f71db4 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -918,7 +918,7 @@ uint64_t helper_cmpteq(uint64_t a, uint64_t b)
     fa = t_to_float64(a);
     fb = t_to_float64(b);
 
-    if (float64_eq(fa, fb, &FP_STATUS))
+    if (float64_eq_quiet(fa, fb, &FP_STATUS))
         return 0x4000000000000000ULL;
     else
         return 0;
@@ -957,7 +957,7 @@ uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
     fa = g_to_float64(a);
     fb = g_to_float64(b);
 
-    if (float64_eq(fa, fb, &FP_STATUS))
+    if (float64_eq_quiet(fa, fb, &FP_STATUS))
         return 0x4000000000000000ULL;
     else
         return 0;
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 986cbe3..ac0f150 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -921,11 +921,11 @@ void helper_ ## name ## sd (Reg *d, Reg *s)\
     d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0));\
 }
 
-#define FPU_CMPEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? -1 : 0
+#define FPU_CMPEQ(size, a, b) float ## size ## _eq_quiet(a, b, &env->sse_status) ? -1 : 0
 #define FPU_CMPLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? -1 : 0
 #define FPU_CMPLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? -1 : 0
 #define FPU_CMPUNORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? - 1 : 0
-#define FPU_CMPNEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? 0 : -1
+#define FPU_CMPNEQ(size, a, b) float ## size ## _eq_quiet(a, b, &env->sse_status) ? 0 : -1
 #define FPU_CMPNLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? 0 : -1
 #define FPU_CMPNLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? 0 : -1
 #define FPU_CMPORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? 0 : -1
@@ -1216,8 +1216,8 @@ void helper_pfadd(MMXReg *d, MMXReg *s)
 
 void helper_pfcmpeq(MMXReg *d, MMXReg *s)
 {
-    d->MMX_L(0) = float32_eq(d->MMX_S(0), s->MMX_S(0), &env->mmx_status) ? -1 : 0;
-    d->MMX_L(1) = float32_eq(d->MMX_S(1), s->MMX_S(1), &env->mmx_status) ? -1 : 0;
+    d->MMX_L(0) = float32_eq_quiet(d->MMX_S(0), s->MMX_S(0), &env->mmx_status) ? -1 : 0;
+    d->MMX_L(1) = float32_eq_quiet(d->MMX_S(1), s->MMX_S(1), &env->mmx_status) ? -1 : 0;
 }
 
 void helper_pfcmpge(MMXReg *d, MMXReg *s)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 39b8ec1..b7cd6b2 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -338,7 +338,7 @@ uint32_t helper_fcmp_eq(uint32_t a, uint32_t b)
     set_float_exception_flags(0, &env->fp_status);
     fa.l = a;
     fb.l = b;
-    r = float32_eq(fa.f, fb.f, &env->fp_status);
+    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
     flags = get_float_exception_flags(&env->fp_status);
     update_fpu_flags(flags & float_flag_invalid);
 
@@ -384,7 +384,7 @@ uint32_t helper_fcmp_ne(uint32_t a, uint32_t b)
     fa.l = a;
     fb.l = b;
     set_float_exception_flags(0, &env->fp_status);
-    r = !float32_eq(fa.f, fb.f, &env->fp_status);
+    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
     flags = get_float_exception_flags(&env->fp_status);
     update_fpu_flags(flags & float_flag_invalid);
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index e9de692..31a19ba 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2893,8 +2893,8 @@ void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
  * but float64_unordered_quiet() is still called. */
 FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
 FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(eq,  !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(eq,  !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(olt, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(ole, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
@@ -2903,8 +2903,8 @@ FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
  * but float64_unordered() is still called. */
 FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
 FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(seq, !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(seq, !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(lt,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
 FOP_COND_D(le,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
@@ -2937,8 +2937,8 @@ void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
  * but float32_unordered_quiet() is still called. */
 FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
 FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
@@ -2947,8 +2947,8 @@ FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
  * but float32_unordered() is still called. */
 FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
 FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
 FOP_COND_S(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
@@ -3000,10 +3000,10 @@ FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status
                  (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
 FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                  !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
@@ -3018,10 +3018,10 @@ FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
                  (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
 FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                  !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
 FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 8c993a1..898ffd0 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3364,7 +3364,7 @@ static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
     CPU_FloatU u1, u2;
     u1.l = op1;
     u2.l = op2;
-    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
+    return float32_eq_quiet(u1.f, u2.f, &env->vec_status) ? 4 : 0;
 }
 
 static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
@@ -3678,7 +3678,7 @@ uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
     CPU_DoubleU u1, u2;
     u1.ll = op1;
     u2.ll = op2;
-    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
+    return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
 }
 
 uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
commit e0b29ce1cf961223a21caa459b14647c1da117ec
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-i386: fix CMPUNORDPS/D and CMPORDPS/D instructions
    
    SSE instructions CMPUNORDPS/D and CMPORDPS/D do not trigger an invalid
    exception if operands are qNANs.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 3232abd..986cbe3 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -924,11 +924,11 @@ void helper_ ## name ## sd (Reg *d, Reg *s)\
 #define FPU_CMPEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? -1 : 0
 #define FPU_CMPLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? -1 : 0
 #define FPU_CMPLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? -1 : 0
-#define FPU_CMPUNORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? - 1 : 0
+#define FPU_CMPUNORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? - 1 : 0
 #define FPU_CMPNEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? 0 : -1
 #define FPU_CMPNLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? 0 : -1
 #define FPU_CMPNLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? 0 : -1
-#define FPU_CMPORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? 0 : -1
+#define FPU_CMPORD(size, a, b) float ## size ## _unordered_quiet(a, b, &env->sse_status) ? 0 : -1
 
 SSE_HELPER_CMP(cmpeq, FPU_CMPEQ)
 SSE_HELPER_CMP(cmplt, FPU_CMPLT)
commit 3a599383592a26f2c614e1a7d92efd1e8eb26c6d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-mips: use new float*_unordered*() functions
    
    Use the new float*_unordered*() functions from softfloat instead of
    redefining a private version.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index bd16ce3..e9de692 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2889,40 +2889,26 @@ void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
         CLEAR_FP_COND(cc, env->active_fpu);                    \
 }
 
-static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
-{
-    if (float64_is_signaling_nan(a) ||
-        float64_is_signaling_nan(b) ||
-        (sig && (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)))) {
-        float_raise(float_flag_invalid, status);
-        return 1;
-    } else if (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_D(f,   (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
-FOP_COND_D(un,  float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(eq,  !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+ * but float64_unordered_quiet() is still called. */
+FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
+FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
+FOP_COND_D(eq,  !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(olt, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ole, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_D(sf,  (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
-FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
-FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(lt,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(le,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
-FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+ * but float64_unordered() is still called. */
+FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
+FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
+FOP_COND_D(seq, !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(lt,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(le,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
+FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
 
 #define FOP_COND_S(op, cond)                                   \
 void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
@@ -2947,40 +2933,26 @@ void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
         CLEAR_FP_COND(cc, env->active_fpu);                    \
 }
 
-static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
-{
-    if (float32_is_signaling_nan(a) ||
-        float32_is_signaling_nan(b) ||
-        (sig && (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)))) {
-        float_raise(float_flag_invalid, status);
-        return 1;
-    } else if (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_S(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
-FOP_COND_S(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
+ * but float32_unordered_quiet() is still called. */
+FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
+FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
+FOP_COND_S(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_S(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
-FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
-FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
-FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
+ * but float32_unordered() is still called. */
+FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
+FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
+FOP_COND_S(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
+FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
 
 #define FOP_COND_PS(op, condl, condh)                           \
 void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
@@ -3023,38 +2995,38 @@ void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
 }
 
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_PS(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
-                 (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
-FOP_COND_PS(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
-                 float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+ * but float32_unordered_quiet() is still called. */
+FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
+                 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
+FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
+FOP_COND_PS(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called. */
-FOP_COND_PS(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
-                 (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
-FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
-                 float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
-FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
-FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
-                 float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+ * but float32_unordered() is still called. */
+FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
+                 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
+FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
+FOP_COND_PS(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
+                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
+                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
commit a4d2d1a063897b859b7f25e414b229370b679bc8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-alpha: use new float64_unordered_quiet() function
    
    Use float64_unordered_quiet() in helper_cmptun() instead of doing the
    the comparison manually.
    
    According to the "Alpha Compiler Writer's Guide", we should use the
    _quiet version here, as CMPTUN and CMPTEQ should generate InvalidOp
    for SNaNs but not for QNaNs.
    
    Thanks to Peter Maydell <peter.maydell at linaro.org> and Richard
    Henderson <rth at twiddle.net> for digging into the manuals.
    
    Acked-by: Richard Henderson  <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 6c2ae20..36f4f6d 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -904,10 +904,11 @@ uint64_t helper_cmptun (uint64_t a, uint64_t b)
     fa = t_to_float64(a);
     fb = t_to_float64(b);
 
-    if (float64_is_quiet_nan(fa) || float64_is_quiet_nan(fb))
+    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
         return 0x4000000000000000ULL;
-    else
+    } else {
         return 0;
+    }
 }
 
 uint64_t helper_cmpteq(uint64_t a, uint64_t b)
commit b4a0ef7911297567e17b56d96ae06d6283049630
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat-native: add float*_unordered_quiet() functions
    
    Add float*_unordered_quiet() functions to march the softfloat versions.
    As FPU status is not tracked with softfloat-native, they don't differ
    from the signaling version.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 80b5f28..406e180 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -237,7 +237,10 @@ INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
 INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
 {
     return isunordered(a, b);
-
+}
+INLINE int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM)
+{
+    return isunordered(a, b);
 }
 int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
@@ -346,7 +349,10 @@ INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
 INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
 {
     return isunordered(a, b);
-
+}
+INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM)
+{
+    return isunordered(a, b);
 }
 int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
@@ -450,7 +456,10 @@ INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
 INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return isunordered(a, b);
-
+}
+INLINE int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM)
+{
+    return isunordered(a, b);
 }
 int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
 int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
commit 67b7861d63f5218fe46809f4f84d4412940b9260
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat: add float*_unordered_{,quiet}() functions
    
    Add float*_unordered() functions to softfloat, matching the softfloat-native
    ones. Also add float*_unordered_quiet() functions to match the others
    comparison functions.
    
    This allow target-i386/ops_sse.h to be compiled with softfloat.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 03fb948..11f6584 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2394,6 +2394,25 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
+| Returns 1 if the single-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  The comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float32_unordered( float32 a, float32 b STATUS_PARAM )
+{
+    a = float32_squash_input_denormal(a STATUS_VAR);
+    b = float32_squash_input_denormal(b STATUS_VAR);
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid STATUS_VAR);
+        return 1;
+    }
+    return 0;
+}
+/*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is equal to
 | the corresponding value `b', and 0 otherwise.  The invalid exception is
 | raised if either operand is a NaN.  Otherwise, the comparison is performed
@@ -2481,6 +2500,29 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
+| Returns 1 if the single-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  Quiet NaNs do not cause an exception.  The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM )
+{
+    a = float32_squash_input_denormal(a STATUS_VAR);
+    b = float32_squash_input_denormal(b STATUS_VAR);
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
+        return 1;
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
 | Returns the result of converting the double-precision floating-point value
 | `a' to the 32-bit two's complement integer format.  The conversion is
 | performed according to the IEC/IEEE Standard for Binary Floating-Point
@@ -3618,6 +3660,26 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
+| Returns 1 if the double-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  The comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float64_unordered( float64 a, float64 b STATUS_PARAM )
+{
+    a = float64_squash_input_denormal(a STATUS_VAR);
+    b = float64_squash_input_denormal(b STATUS_VAR);
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid STATUS_VAR);
+        return 1;
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is equal to the
 | corresponding value `b', and 0 otherwise.  The invalid exception is raised
 | if either operand is a NaN.  Otherwise, the comparison is performed
@@ -3704,6 +3766,29 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
 
 }
 
+/*----------------------------------------------------------------------------
+| Returns 1 if the double-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  Quiet NaNs do not cause an exception.  The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM )
+{
+    a = float64_squash_input_denormal(a STATUS_VAR);
+    b = float64_squash_input_denormal(b STATUS_VAR);
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
+        return 1;
+    }
+    return 0;
+}
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -4597,6 +4682,24 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point values `a' and `b'
+| cannot be compared, and 0 otherwise.  The comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM )
+{
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        float_raise( float_flag_invalid STATUS_VAR);
+        return 1;
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is equal
 | to the corresponding value `b', and 0 otherwise.  The invalid exception is
 | raised if either operand is a NaN.  Otherwise, the comparison is performed
@@ -4695,6 +4798,28 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 
 }
 
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point values `a' and `b'
+| cannot be compared, and 0 otherwise.  Quiet NaNs do not cause an exception.
+| The comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+{
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        if (    floatx80_is_signaling_nan( a )
+             || floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
+        return 1;
+    }
+    return 0;
+}
+
 #endif
 
 #ifdef FLOAT128
@@ -5718,6 +5843,25 @@ int float128_lt( float128 a, float128 b STATUS_PARAM )
 }
 
 /*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  The comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float128_unordered( float128 a, float128 b STATUS_PARAM )
+{
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        float_raise( float_flag_invalid STATUS_VAR);
+        return 1;
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is equal to
 | the corresponding value `b', and 0 otherwise.  The invalid exception is
 | raised if either operand is a NaN.  Otherwise, the comparison is performed
@@ -5816,6 +5960,29 @@ int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
 
 }
 
+/*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
+| be compared, and 0 otherwise.  Quiet NaNs do not cause an exception.  The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM )
+{
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        if (    float128_is_signaling_nan( a )
+             || float128_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid STATUS_VAR);
+        }
+        return 1;
+    }
+    return 0;
+}
+
 #endif
 
 /* misc functions */
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index c7654d4..55c0c1c 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -323,9 +323,11 @@ float32 float32_log2( float32 STATUS_PARAM );
 int float32_eq( float32, float32 STATUS_PARAM );
 int float32_le( float32, float32 STATUS_PARAM );
 int float32_lt( float32, float32 STATUS_PARAM );
+int float32_unordered( float32, float32 STATUS_PARAM );
 int float32_eq_signaling( float32, float32 STATUS_PARAM );
 int float32_le_quiet( float32, float32 STATUS_PARAM );
 int float32_lt_quiet( float32, float32 STATUS_PARAM );
+int float32_unordered_quiet( float32, float32 STATUS_PARAM );
 int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
 float32 float32_min(float32, float32 STATUS_PARAM);
@@ -437,9 +439,11 @@ float64 float64_log2( float64 STATUS_PARAM );
 int float64_eq( float64, float64 STATUS_PARAM );
 int float64_le( float64, float64 STATUS_PARAM );
 int float64_lt( float64, float64 STATUS_PARAM );
+int float64_unordered( float64, float64 STATUS_PARAM );
 int float64_eq_signaling( float64, float64 STATUS_PARAM );
 int float64_le_quiet( float64, float64 STATUS_PARAM );
 int float64_lt_quiet( float64, float64 STATUS_PARAM );
+int float64_unordered_quiet( float64, float64 STATUS_PARAM );
 int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
 float64 float64_min(float64, float64 STATUS_PARAM);
@@ -538,9 +542,11 @@ floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
 int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
+int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
 int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
 int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_is_quiet_nan( floatx80 );
 int floatx80_is_signaling_nan( floatx80 );
 floatx80 floatx80_maybe_silence_nan( floatx80 );
@@ -621,9 +627,11 @@ float128 float128_sqrt( float128 STATUS_PARAM );
 int float128_eq( float128, float128 STATUS_PARAM );
 int float128_le( float128, float128 STATUS_PARAM );
 int float128_lt( float128, float128 STATUS_PARAM );
+int float128_unordered( float128, float128 STATUS_PARAM );
 int float128_eq_signaling( float128, float128 STATUS_PARAM );
 int float128_le_quiet( float128, float128 STATUS_PARAM );
 int float128_lt_quiet( float128, float128 STATUS_PARAM );
+int float128_unordered_quiet( float128, float128 STATUS_PARAM );
 int float128_compare( float128, float128 STATUS_PARAM );
 int float128_compare_quiet( float128, float128 STATUS_PARAM );
 int float128_is_quiet_nan( float128 );
commit 67dd64bfae87b4464b880de03c1d04f5f605d48d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-i386: add floatx_{add,mul,sub} and use them
    
    Add floatx_{add,mul,sub} defines, and use them instead of using direct
    C operations.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 63a23cd..ae6b947 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -110,6 +110,9 @@ static inline void svm_check_intercept(uint32_t type)
 #define float64_to_floatx float64_to_floatx80
 #define floatx_to_float32 floatx80_to_float32
 #define floatx_to_float64 floatx80_to_float64
+#define floatx_add floatx80_add
+#define floatx_mul floatx80_mul
+#define floatx_sub floatx80_sub
 #define floatx_abs floatx80_abs
 #define floatx_chs floatx80_chs
 #define floatx_round_to_int floatx80_round_to_int
@@ -126,6 +129,9 @@ static inline void svm_check_intercept(uint32_t type)
 #define float64_to_floatx(x, e) (x)
 #define floatx_to_float32 float64_to_float32
 #define floatx_to_float64(x, e) (x)
+#define floatx_add float64_add
+#define floatx_mul float64_mul
+#define floatx_sub float64_sub
 #define floatx_abs float64_abs
 #define floatx_chs float64_chs
 #define floatx_round_to_int float64_round_to_int
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 43fbd0c..a73427f 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3711,22 +3711,22 @@ void helper_fucomi_ST0_FT0(void)
 
 void helper_fadd_ST0_FT0(void)
 {
-    ST0 += FT0;
+    ST0 = floatx_add(ST0, FT0, &env->fp_status);
 }
 
 void helper_fmul_ST0_FT0(void)
 {
-    ST0 *= FT0;
+    ST0 = floatx_mul(ST0, FT0, &env->fp_status);
 }
 
 void helper_fsub_ST0_FT0(void)
 {
-    ST0 -= FT0;
+    ST0 = floatx_sub(ST0, FT0, &env->fp_status);
 }
 
 void helper_fsubr_ST0_FT0(void)
 {
-    ST0 = FT0 - ST0;
+    ST0 = floatx_sub(FT0, ST0, &env->fp_status);
 }
 
 void helper_fdiv_ST0_FT0(void)
@@ -3743,24 +3743,22 @@ void helper_fdivr_ST0_FT0(void)
 
 void helper_fadd_STN_ST0(int st_index)
 {
-    ST(st_index) += ST0;
+    ST(st_index) = floatx_add(ST(st_index), ST0, &env->fp_status);
 }
 
 void helper_fmul_STN_ST0(int st_index)
 {
-    ST(st_index) *= ST0;
+    ST(st_index) = floatx_mul(ST(st_index), ST0, &env->fp_status);
 }
 
 void helper_fsub_STN_ST0(int st_index)
 {
-    ST(st_index) -= ST0;
+    ST(st_index) = floatx_sub(ST(st_index), ST0, &env->fp_status);
 }
 
 void helper_fsubr_STN_ST0(int st_index)
 {
-    CPU86_LDouble *p;
-    p = &ST(st_index);
-    *p = ST0 - *p;
+    ST(st_index) = floatx_sub(ST0, ST(st_index), &env->fp_status);
 }
 
 void helper_fdiv_STN_ST0(int st_index)
commit c41372230e441cb28dcf246d5f2a3226830156bd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-i386: use float unions from cpu-all.h
    
    Use float unions from cpu-all.h instead of redefining new (wrong for arm)
    ones in target-i386. This also allows building cpu-exec.o with softfloat.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 6f9f709..63a23cd 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -144,13 +144,7 @@ static inline void svm_check_intercept(uint32_t type)
 #ifdef USE_X86LDOUBLE
 
 /* only for x86 */
-typedef union {
-    long double d;
-    struct {
-        unsigned long long lower;
-        unsigned short upper;
-    } l;
-} CPU86_LDoubleU;
+typedef CPU_LDoubleU CPU86_LDoubleU;
 
 /* the following deal with x86 long double-precision numbers */
 #define MAXEXPD 0x7fff
@@ -162,24 +156,7 @@ typedef union {
 
 #else
 
-/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
-typedef union {
-    double d;
-#if !defined(HOST_WORDS_BIGENDIAN) && !defined(__arm__)
-    struct {
-        uint32_t lower;
-        int32_t upper;
-    } l;
-#else
-    struct {
-        int32_t upper;
-        uint32_t lower;
-    } l;
-#endif
-#ifndef __arm__
-    int64_t ll;
-#endif
-} CPU86_LDoubleU;
+typedef CPU_DoubleU CPU86_LDoubleU;
 
 /* the following deal with IEEE double-precision numbers */
 #define MAXEXPD 0x7ff
commit 1ffd41ee0c5b3409492d237201d50b78578064e5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    target-i386: use CPU_LDoubleU instead of a private union
    
    Use CPU_LDoubleU in cpu_dump_state() instead of redefining a union for
    doing the conversion.
    
    Based on a patch from Laurent Vivier <laurent at vivier.eu>.
    
    Cc: Laurent Vivier <laurent at vivier.eu>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index d15fca5..89df997 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -404,16 +404,10 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                     env->mxcsr);
         for(i=0;i<8;i++) {
 #if defined(USE_X86LDOUBLE)
-            union {
-                long double d;
-                struct {
-                    uint64_t lower;
-                    uint16_t upper;
-                } l;
-            } tmp;
-            tmp.d = env->fpregs[i].d;
+            CPU_LDoubleU u;
+            u.d = env->fpregs[i].d;
             cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
-                        i, tmp.l.lower, tmp.l.upper);
+                        i, u.l.lower, u.l.upper);
 #else
             cpu_fprintf(f, "FPR%d=%016" PRIx64,
                         i, env->fpregs[i].mmx.q);
commit 602308f0f54daa7503ea0f4909b51aef5f3b0ca1
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    cpu-all.h: define CPU_LDoubleU
    
    Add a CPU_LDoubleU type, matching the floatx80 definition and the long
    double type on x86 hosts.
    
    Based on a patch from Laurent Vivier <laurent at vivier.eu>.
    
    Cc: Laurent Vivier <laurent at vivier.eu>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-all.h b/cpu-all.h
index dc0f2f0..0bae6df 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -138,6 +138,16 @@ typedef union {
     uint64_t ll;
 } CPU_DoubleU;
 
+#if defined(FLOATX80)
+typedef union {
+     floatx80 d;
+     struct {
+         uint64_t lower;
+         uint16_t upper;
+     } l;
+} CPU_LDoubleU;
+#endif
+
 #if defined(CONFIG_SOFTFLOAT)
 typedef union {
     float128 q;
commit b3b4c7f33fc8e51db75bf4abaf4a631c2f1fb23b
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Apr 14 00:49:29 2011 +0200

    softfloat: use GCC builtins to count the leading zeros
    
    Softfloat has its own implementation to count the leading zeros. However
    a lot of architectures have either a dedicated instruction or an
    optimized to do that. When using GCC >= 3.4, this patch uses GCC builtins
    instead of the handcoded implementation.
    
    Note that I amware that QEMU_GNUC_PREREQ is defined in osdep.h and that
    clz32() and clz64() are defined in host-utils.h, but I think it is better
    to keep the softfloat implementation self contained.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index 3128e60..e82ce23 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -36,6 +36,17 @@ these four paragraphs for those parts of this code that are retained.
 =============================================================================*/
 
 /*----------------------------------------------------------------------------
+| This macro tests for minimum version of the GNU C compiler.
+*----------------------------------------------------------------------------*/
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define SOFTFLOAT_GNUC_PREREQ(maj, min) \
+         ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define SOFTFLOAT_GNUC_PREREQ(maj, min) 0
+#endif
+
+
+/*----------------------------------------------------------------------------
 | Shifts `a' right by the number of bits given in `count'.  If any nonzero
 | bits are shifted off, they are ``jammed'' into the least significant bit of
 | the result by setting the least significant bit to 1.  The value of `count'
@@ -616,6 +627,13 @@ static uint32_t estimateSqrt32( int16 aExp, uint32_t a )
 
 static int8 countLeadingZeros32( uint32_t a )
 {
+#if SOFTFLOAT_GNUC_PREREQ(3, 4)
+    if (a) {
+        return __builtin_clz(a);
+    } else {
+        return 32;
+    }
+#else
     static const int8 countLeadingZerosHigh[] = {
         8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -647,7 +665,7 @@ static int8 countLeadingZeros32( uint32_t a )
     }
     shiftCount += countLeadingZerosHigh[ a>>24 ];
     return shiftCount;
-
+#endif
 }
 
 /*----------------------------------------------------------------------------
@@ -657,6 +675,13 @@ static int8 countLeadingZeros32( uint32_t a )
 
 static int8 countLeadingZeros64( uint64_t a )
 {
+#if SOFTFLOAT_GNUC_PREREQ(3, 4)
+    if (a) {
+        return __builtin_clzll(a);
+    } else {
+        return 64;
+    }
+#else
     int8 shiftCount;
 
     shiftCount = 0;
@@ -668,7 +693,7 @@ static int8 countLeadingZeros64( uint64_t a )
     }
     shiftCount += countLeadingZeros32( a );
     return shiftCount;
-
+#endif
 }
 
 /*----------------------------------------------------------------------------
commit a0102082de4026833afbd2525e8a6320d1f92885
Author: Brad Hards <bradh at frogmouth.net>
Date:   Wed Apr 13 19:45:33 2011 +1000

    usb: fix spelling errors in usb-linux.c
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/usb-linux.c b/usb-linux.c
index d958853..1f33c2c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -107,7 +107,7 @@ enum {
 /*
  * Control transfer state.
  * Note that 'buffer' _must_ follow 'req' field because
- * we need contigious buffer when we submit control URB.
+ * we need contiguous buffer when we submit control URB.
  */
 struct ctrl_struct {
     uint16_t len;
@@ -580,7 +580,7 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
     /*
      * Setup ctrl transfer.
      *
-     * s->ctrl is layed out such that data buffer immediately follows
+     * s->ctrl is laid out such that data buffer immediately follows
      * 'req' struct which is exactly what usbdevfs expects.
      */
     urb = &aurb->urb;
commit 021730f7285923460e81004c9dae74b6a1c8aa0c
Author: Brad Hards <bradh at frogmouth.net>
Date:   Wed Apr 13 19:45:32 2011 +1000

    usb: initialise data element in Linux USB_DISCONNECT ioctl
    
    This isn't used, but leaving it empty causes valgrind noise.
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/usb-linux.c b/usb-linux.c
index 255009f..d958853 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -344,6 +344,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
         for (interface = 0; interface < nb_interfaces; interface++) {
             ctrl.ioctl_code = USBDEVFS_DISCONNECT;
             ctrl.ifno = interface;
+            ctrl.data = 0;
             ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
             if (ret < 0 && errno != ENODATA) {
                 perror("USBDEVFS_DISCONNECT");
commit 94843f66ab06f45240d2afa7a648c5722da14dfb
Author: Brad Hards <bradh at frogmouth.net>
Date:   Wed Apr 13 19:45:31 2011 +1000

    usb: trivial spelling fixes
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 76f5b02..947fd3f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -33,7 +33,7 @@ do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
 
 enum USBMSDMode {
     USB_MSDM_CBW, /* Command Block.  */
-    USB_MSDM_DATAOUT, /* Tranfer data to device.  */
+    USB_MSDM_DATAOUT, /* Transfer data to device.  */
     USB_MSDM_DATAIN, /* Transfer data from device.  */
     USB_MSDM_CSW /* Command Status.  */
 };
@@ -253,7 +253,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
         usb_msd_copy_data(s);
         if (s->usb_len == 0) {
             /* Set s->packet to NULL before calling usb_packet_complete
-               because annother request may be issued before
+               because another request may be issued before
                usb_packet_complete returns.  */
             DPRINTF("Packet complete %p\n", p);
             s->packet = NULL;
commit 7a734b8f68b4a72aba90c3abd9a52e341f4c996a
Author: Brad Hards <bradh at frogmouth.net>
Date:   Wed Apr 13 16:42:16 2011 +1000

    Makefile: Clean up after "make pdf"
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/.gitignore b/.gitignore
index 1d79680..08013fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,9 @@ QMP/qmp-commands.txt
 *.ky
 *.log
 *.pdf
+*.cps
+*.fns
+*.kys
 *.pg
 *.pyc
 *.toc
diff --git a/Makefile b/Makefile
index fa93be5..dc39efd 100644
--- a/Makefile
+++ b/Makefile
@@ -163,7 +163,10 @@ distclean: clean
 	rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
 	rm -f config-all-devices.mak
 	rm -f roms/seabios/config.mak roms/vgabios/config.mak
-	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
+	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi
+	rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys
+	rm -f qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp
+	rm -f qemu-doc.vr
 	rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
 	for d in $(TARGET_DIRS) $(QEMULIBS); do \
 	rm -rf $$d || exit 1 ; \
commit 61cc8701f3e019f154c3662f3c9f998629813745
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Apr 13 22:45:22 2011 +0200

    Fix some typos in comments and documentation
    
    helpfull -> helpful
    usefull -> useful
    cotrol -> control
    
    and a grammar fix.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index ef60730..677c550 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -937,8 +937,8 @@ a lot of bandwidth at the expense of quality.
 Disable adaptive encodings. Adaptive encodings are enabled by default.
 An adaptive encoding will try to detect frequently updated screen regions,
 and send updates in these regions using a lossy encoding (like JPEG).
-This can be really helpfull to save bandwidth when playing videos. Disabling
-adaptive encodings allow to restore the original static behavior of encodings
+This can be really helpful to save bandwidth when playing videos. Disabling
+adaptive encodings allows to restore the original static behavior of encodings
 like Tight.
 
 @end table
diff --git a/savevm.c b/savevm.c
index be44fdb..f4ff1a1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1008,7 +1008,7 @@ const VMStateInfo vmstate_info_buffer = {
 };
 
 /* unused buffers: space that was used for some fields that are
-   not usefull anymore */
+   not useful anymore */
 
 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
 {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9172fc7..a0ec643 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1378,7 +1378,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
             /* This may enable/disable the MMU, so do a TLB flush.  */
             tlb_flush(env, 1);
             break;
-        case 1: /* Auxiliary cotrol register.  */
+        case 1: /* Auxiliary control register.  */
             if (arm_feature(env, ARM_FEATURE_XSCALE)) {
                 env->cp15.c1_xscaleauxcr = val;
                 break;
commit adc56dda0c4eed62149d28939b7d7e329ad95ae8
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 3 08:23:19 2011 +0000

    migration: move some declarations to migration.h
    
    Move a few migration related declarations to migration.h.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/arch_init.h b/arch_init.h
index c83360c..86ebc14 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -22,8 +22,6 @@ enum {
 extern const uint32_t arch_type;
 
 void select_soundhw(const char *optarg);
-int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
-int ram_load(QEMUFile *f, void *opaque, int version_id);
 void do_acpitable_option(const char *optarg);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
diff --git a/migration.h b/migration.h
index 2170792..050c56c 100644
--- a/migration.h
+++ b/migration.h
@@ -139,4 +139,13 @@ void add_migration_state_change_notifier(Notifier *notify);
 void remove_migration_state_change_notifier(Notifier *notify);
 int get_migration_state(void);
 
+uint64_t ram_bytes_remaining(void);
+uint64_t ram_bytes_transferred(void);
+uint64_t ram_bytes_total(void);
+
+int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
+int ram_load(QEMUFile *f, void *opaque, int version_id);
+
+extern int incoming_expected;
+
 #endif
diff --git a/sysemu.h b/sysemu.h
index 6effd8a..b0296a0 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -37,10 +37,6 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
 void vm_start(void);
 void vm_stop(int reason);
 
-uint64_t ram_bytes_remaining(void);
-uint64_t ram_bytes_transferred(void);
-uint64_t ram_bytes_total(void);
-
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
@@ -89,7 +85,6 @@ typedef enum DisplayType
 } DisplayType;
 
 extern int autostart;
-extern int incoming_expected;
 extern int bios_size;
 
 typedef enum {
commit 17a4663e2dddbac36126a6fd7048634a4c95fa6e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 16:05:08 2011 +0000

    Move CPU related functions to cpus.h
    
    Move declarations of CPU related functions to cpus.h. Adjust the only user.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.h b/cpus.h
index e021126..6fdeb0d 100644
--- a/cpus.h
+++ b/cpus.h
@@ -8,6 +8,10 @@ void resume_all_vcpus(void);
 void pause_all_vcpus(void);
 void cpu_stop_current(void);
 
+void cpu_synchronize_all_states(void);
+void cpu_synchronize_all_post_reset(void);
+void cpu_synchronize_all_post_init(void);
+
 /* vl.c */
 extern int smp_cores;
 extern int smp_threads;
diff --git a/savevm.c b/savevm.c
index 03fce62..be44fdb 100644
--- a/savevm.c
+++ b/savevm.c
@@ -82,6 +82,7 @@
 #include "migration.h"
 #include "qemu_socket.h"
 #include "qemu-queue.h"
+#include "cpus.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
diff --git a/sysemu.h b/sysemu.h
index a379024..6effd8a 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -64,10 +64,6 @@ int load_vmstate(const char *name);
 void do_delvm(Monitor *mon, const QDict *qdict);
 void do_info_snapshots(Monitor *mon);
 
-void cpu_synchronize_all_states(void);
-void cpu_synchronize_all_post_reset(void);
-void cpu_synchronize_all_post_init(void);
-
 void qemu_announce_self(void);
 
 void main_loop_wait(int nonblocking);
commit 70c3b5575ee3e0d528aa176c8c5add3e7355c01e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 15:45:39 2011 +0000

    Move clock related functions to qemu-timer.h
    
    Move declarations for clock related functions from sysemu.h to qemu-timer.h.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-timer.h b/qemu-timer.h
index 3a9228f..bbc3452 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -59,6 +59,10 @@ void init_clocks(void);
 int init_timer_alarm(void);
 void quit_timers(void);
 
+int64_t cpu_get_ticks(void);
+void cpu_enable_ticks(void);
+void cpu_disable_ticks(void);
+
 static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
                                            void *opaque)
 {
diff --git a/sysemu.h b/sysemu.h
index f112c22..a379024 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -41,10 +41,6 @@ uint64_t ram_bytes_remaining(void);
 uint64_t ram_bytes_transferred(void);
 uint64_t ram_bytes_total(void);
 
-int64_t cpu_get_ticks(void);
-void cpu_enable_ticks(void);
-void cpu_disable_ticks(void);
-
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
commit 082b5557996764fb21ba8cff17aabec7242ed342
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 09:04:57 2011 +0000

    Move generic or OS function declarations to qemu-common.h
    
    Move generic or OS related function declarations and macro
    TFR to qemu-common.h.
    
    Move win32 include directives to qemu-os-win32.h. While moving,
    also add #include <winsock2.h> to fix a recent mingw32
    build breakage.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-common.h b/qemu-common.h
index 4f6037b..f9f705d 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -12,6 +12,7 @@
 #endif
 
 #define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
+#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
 typedef struct QEMUTimer QEMUTimer;
 typedef struct QEMUFile QEMUFile;
@@ -39,6 +40,14 @@ typedef struct Monitor Monitor;
 #include <sys/time.h>
 #include <assert.h>
 
+#ifdef _WIN32
+#include "qemu-os-win32.h"
+#endif
+
+#ifdef CONFIG_POSIX
+#include "qemu-os-posix.h"
+#endif
+
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
 #endif
@@ -339,6 +348,16 @@ void qemu_progress_init(int enabled, float min_skip);
 void qemu_progress_end(void);
 void qemu_progress_print(float percent, int max);
 
+#define QEMU_FILE_TYPE_BIOS   0
+#define QEMU_FILE_TYPE_KEYMAP 1
+char *qemu_find_file(int type, const char *name);
+
+/* OS specific functions */
+void os_setup_early_signal_handling(void);
+char *os_find_datadir(const char *argv0);
+void os_parse_cmd_args(int index, const char *optarg);
+void os_pidfile_error(void);
+
 /* Convert a byte between binary and BCD.  */
 static inline uint8_t to_bcd(uint8_t val)
 {
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 1a07e5e..ed2753d 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -26,6 +26,9 @@
 #ifndef QEMU_OS_WIN32_H
 #define QEMU_OS_WIN32_H
 
+#include <windows.h>
+#include <winsock2.h>
+
 /* Polling handling */
 
 /* return TRUE if no sleep should be done afterwards */
diff --git a/sysemu.h b/sysemu.h
index bbbd0fd..f112c22 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -8,22 +8,9 @@
 #include "qemu-timer.h"
 #include "notify.h"
 
-#ifdef _WIN32
-#include <windows.h>
-#include "qemu-os-win32.h"
-#endif
-
-#ifdef CONFIG_POSIX
-#include "qemu-os-posix.h"
-#endif
-
 /* vl.c */
 extern const char *bios_name;
 
-#define QEMU_FILE_TYPE_BIOS   0
-#define QEMU_FILE_TYPE_KEYMAP 1
-char *qemu_find_file(int type, const char *name);
-
 extern int vm_running;
 extern const char *qemu_name;
 extern uint8_t qemu_uuid[];
@@ -100,12 +87,6 @@ int qemu_loadvm_state(QEMUFile *f);
 /* SLIRP */
 void do_info_slirp(Monitor *mon);
 
-/* OS specific functions */
-void os_setup_early_signal_handling(void);
-char *os_find_datadir(const char *argv0);
-void os_parse_cmd_args(int index, const char *optarg);
-void os_pidfile_error(void);
-
 typedef enum DisplayType
 {
     DT_DEFAULT,
@@ -191,8 +172,6 @@ extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 
 extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 
-#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
-
 void do_usb_add(Monitor *mon, const QDict *qdict);
 void do_usb_del(Monitor *mon, const QDict *qdict);
 void usb_info(Monitor *mon);
commit d8dfad9c41c3431dbb97ad722a93e6ad1e9e9279
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 14:31:31 2011 +0000

    Use qemu-common.h or qemu-timer.h in place of sysemu.h
    
    In some cases qemu-common.h or qemu-timer.h can be used in place
    of sysemu.h.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pcie.c b/hw/pcie.c
index 6a113a9..9de6149 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -18,8 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysemu.h"
-#include "range.h"
+#include "qemu-common.h"
 #include "pci_bridge.h"
 #include "pcie.h"
 #include "msix.h"
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index c25362c..89c293c 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -26,7 +26,7 @@
 #include "console.h"
 #include "usb.h"
 #include "usb-desc.h"
-#include "sysemu.h"
+#include "qemu-timer.h"
 
 /* HID interface requests */
 #define GET_REPORT   0xa101
diff --git a/net/dump.c b/net/dump.c
index 83eda0f..0d0cbb2 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -24,9 +24,9 @@
 
 #include "dump.h"
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "qemu-error.h"
 #include "qemu-log.h"
+#include "qemu-timer.h"
 
 typedef struct DumpState {
     VLANClientState nc;
commit a08784dd11794fc60fcc724c7ef2cd1a75a5356d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 14:12:29 2011 +0000

    Remove unused sysemu.h include directives
    
    Remove unused sysemu.h include directives to speed up build
    with the following patches.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/acl.c b/acl.c
index 311dade..82c2704 100644
--- a/acl.c
+++ b/acl.c
@@ -24,7 +24,6 @@
 
 
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "acl.h"
 
 #ifdef CONFIG_FNMATCH
diff --git a/arm-semi.c b/arm-semi.c
index 1d5179b..e9e6f89 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -33,7 +33,6 @@
 #define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
 #else
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "gdbstub.h"
 #endif
 
diff --git a/balloon.c b/balloon.c
index 0021fef..248c1b5 100644
--- a/balloon.c
+++ b/balloon.c
@@ -22,7 +22,6 @@
  * THE SOFTWARE.
  */
 
-#include "sysemu.h"
 #include "monitor.h"
 #include "qjson.h"
 #include "qint.h"
diff --git a/bt-host.c b/bt-host.c
index 6931e7c..095254d 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -19,7 +19,6 @@
 
 #include "qemu-common.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "net.h"
 #include "bt-host.h"
 
diff --git a/bt-vhci.c b/bt-vhci.c
index 679c5e0..3c57720 100644
--- a/bt-vhci.c
+++ b/bt-vhci.c
@@ -19,7 +19,6 @@
 
 #include "qemu-common.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "net.h"
 #include "hw/bt.h"
 
diff --git a/buffered_file.c b/buffered_file.c
index b5e2baf..41b42c3 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -14,7 +14,6 @@
 #include "qemu-common.h"
 #include "hw/hw.h"
 #include "qemu-timer.h"
-#include "sysemu.h"
 #include "qemu-char.h"
 #include "buffered_file.h"
 
diff --git a/device_tree.c b/device_tree.c
index 21be070..f5d5eb1 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -20,7 +20,6 @@
 
 #include "config.h"
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "device_tree.h"
 #include "hw/loader.h"
 
diff --git a/hw/an5206.c b/hw/an5206.c
index b9f19a9..42a0163 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -9,7 +9,6 @@
 #include "hw.h"
 #include "pc.h"
 #include "mcf.h"
-#include "sysemu.h"
 #include "boards.h"
 #include "loader.h"
 #include "elf.h"
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 304cd34..72d010a 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 #include "arm-misc.h"
-#include "sysemu.h"
 #include "loader.h"
 #include "elf.h"
 
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 57b5e2f..0e2135a 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -26,7 +26,6 @@
 #include "net.h"
 #include "flash.h"
 #include "boards.h"
-#include "sysemu.h"
 #include "etraxfs.h"
 #include "loader.h"
 #include "elf.h"
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 5f329ad..c524550 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -19,7 +19,6 @@
  */
 
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "console.h"
 #include "devices.h"
 #include "vga_int.h"
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 65ffa37..d135ef4 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -22,7 +22,6 @@
 #include "qemu-char.h"
 #include "qemu-timer.h"
 #include "irq.h"
-#include "sysemu.h"
 #include "net.h"
 #include "bt.h"
 
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index 2ef17f6..37894f8 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -23,7 +23,6 @@
  */
 
 #include "hw.h"
-#include "sysemu.h"
 #include "loader.h"
 #include "elf.h"
 #include "cris-boot.h"
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 61efb39..cec1cc8 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -7,7 +7,6 @@
  */
 
 #include "hw.h"
-#include "sysemu.h"
 #include "boards.h"
 #include "loader.h"
 #include "elf.h"
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 5ee5f97..b84d74a 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -24,7 +24,6 @@
 
 #include "sysbus.h"
 #include "boards.h"
-#include "sysemu.h"
 #include "net.h"
 #include "flash.h"
 #include "etraxfs.h"
diff --git a/hw/gumstix.c b/hw/gumstix.c
index ee63f63..853f7e1 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -35,7 +35,6 @@
 #include "pxa.h"
 #include "net.h"
 #include "flash.h"
-#include "sysemu.h"
 #include "devices.h"
 #include "boards.h"
 #include "blockdev.h"
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index f242d7a..a3d475c 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -67,7 +67,6 @@
 #include <hw/isa.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/pci.h>
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 8c59c5a..4ac7453 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -27,7 +27,6 @@
 #include <hw/isa.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index c1b4caa..7107f6b 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -27,7 +27,6 @@
 #include <hw/mac_dbdma.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 2ceeb87..9fbbf0e 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -27,7 +27,6 @@
 #include <hw/pcmcia.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 82b24b6..10f6f40 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -25,7 +25,6 @@
 #include <hw/hw.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 35168cb..65cb56c 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -28,7 +28,6 @@
 #include <hw/isa.h>
 #include "block.h"
 #include "block_int.h"
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/pci.h>
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index b049940..a6c27be 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -10,7 +10,6 @@
 #include "sysbus.h"
 #include "primecell.h"
 #include "devices.h"
-#include "sysemu.h"
 #include "boards.h"
 #include "arm-misc.h"
 #include "net.h"
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index d07aa41..2765543 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -17,7 +17,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "hw.h"
-#include "sysemu.h"
 #include "monitor.h"
 #include "sysbus.h"
 #include "isa.h"
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 85190f0..6462923 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -21,7 +21,6 @@
 #include "hw.h"
 #include "net.h"
 #include "flash.h"
-#include "sysemu.h"
 #include "devices.h"
 #include "boards.h"
 #include "loader.h"
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 50691ca..4792f0e 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -14,7 +14,6 @@
 #include "net.h"
 #include "devices.h"
 #include "boards.h"
-#include "sysemu.h"
 #include "flash.h"
 #include "blockdev.h"
 #include "sysbus.h"
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 06bccbd..a7b687b 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -26,7 +26,6 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "hw.h"
-#include "sysemu.h"
 #include "console.h"
 #include "omap.h"
 #include "boards.h"
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 645e84f..20b8629 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -17,7 +17,6 @@
 #include "hw.h"
 #include "pci.h"
 #include "boards.h"
-#include "sysemu.h"
 #include "ppc440.h"
 #include "kvm.h"
 #include "kvm_ppc.h"
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 5f581fe..7f9ed17 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -24,7 +24,6 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc4xx.h"
-#include "sysemu.h"
 #include "qemu-log.h"
 
 //#define DEBUG_MMIO
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 0d52926..7932c24 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -14,7 +14,6 @@
 #include "qemu-timer.h"
 #include "i2c.h"
 #include "net.h"
-#include "sysemu.h"
 #include "boards.h"
 
 #define GPIO_A 0
diff --git a/hw/syborg.c b/hw/syborg.c
index 758c69a..bc200e4 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -25,7 +25,6 @@
 #include "sysbus.h"
 #include "boards.h"
 #include "arm-misc.h"
-#include "sysemu.h"
 #include "net.h"
 
 static struct arm_boot_info syborg_binfo;
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index ee08c49..2f3e6da 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -26,7 +26,6 @@
 #include "sysbus.h"
 #include "virtio.h"
 #include "virtio-net.h"
-#include "sysemu.h"
 
 //#define DEBUG_SYBORG_VIRTIO
 
diff --git a/hw/sysbus.c b/hw/sysbus.c
index acad72a..2e22be7 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -18,7 +18,6 @@
  */
 
 #include "sysbus.h"
-#include "sysemu.h"
 #include "monitor.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
diff --git a/hw/tc58128.c b/hw/tc58128.c
index 672a01c..61b99dd 100644
--- a/hw/tc58128.c
+++ b/hw/tc58128.c
@@ -1,6 +1,5 @@
 #include "hw.h"
 #include "sh.h"
-#include "sysemu.h"
 #include "loader.h"
 
 #define CE1  0x0100
diff --git a/hw/tosa.c b/hw/tosa.c
index b8b6c4f..a7967a2 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -11,7 +11,6 @@
 #include "hw.h"
 #include "pxa.h"
 #include "arm-misc.h"
-#include "sysemu.h"
 #include "devices.h"
 #include "sharpsl.h"
 #include "pcmcia.h"
diff --git a/hw/twl92230.c b/hw/twl92230.c
index 8e74acc..a75448f 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -22,7 +22,6 @@
 #include "hw.h"
 #include "qemu-timer.h"
 #include "i2c.h"
-#include "sysemu.h"
 #include "console.h"
 
 #define VERBOSE 1
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 257baf8..70a8710 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -15,7 +15,6 @@
 #include "qemu-common.h"
 #include "virtio.h"
 #include "pc.h"
-#include "sysemu.h"
 #include "cpu.h"
 #include "monitor.h"
 #include "balloon.h"
diff --git a/hw/virtio.c b/hw/virtio.c
index 31bd9e3..6e8814c 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -16,7 +16,6 @@
 #include "trace.h"
 #include "qemu-error.h"
 #include "virtio.h"
-#include "sysemu.h"
 
 /* The alignment to use between consumer and producer parts of vring.
  * x86 pagesize again. */
diff --git a/hw/vmport.c b/hw/vmport.c
index 19010e4..c8aefaa 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -24,7 +24,6 @@
 #include "hw.h"
 #include "isa.h"
 #include "pc.h"
-#include "sysemu.h"
 #include "kvm.h"
 #include "qdev.h"
 
diff --git a/hw/xen_console.c b/hw/xen_console.c
index d2261f4..c6c8163 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -33,7 +33,6 @@
 #include <xenctrl.h>
 
 #include "hw.h"
-#include "sysemu.h"
 #include "qemu-char.h"
 #include "xen_backend.h"
 
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index 371c562..4093587 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -1,7 +1,6 @@
 #include <signal.h>
 #include "xen_backend.h"
 #include "xen_domainbuild.h"
-#include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-log.h"
 
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 77a34bf..0d7f73e 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -24,7 +24,6 @@
 
 #include "hw.h"
 #include "pc.h"
-#include "sysemu.h"
 #include "boards.h"
 #include "xen_backend.h"
 #include "xen_domainbuild.h"
diff --git a/hw/xenfb.c b/hw/xenfb.c
index da5297b..1db75fb 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -44,7 +44,6 @@
 #include <xen/io/protocols.h>
 
 #include "hw.h"
-#include "sysemu.h"
 #include "console.h"
 #include "qemu-char.h"
 #include "xen_backend.h"
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 30827b0..d398c18 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -23,7 +23,6 @@
  */
 
 #include "sysbus.h"
-#include "sysemu.h"
 #include "qemu-timer.h"
 
 #define D(x)
diff --git a/kvm-stub.c b/kvm-stub.c
index 30f6ec3..1c95452 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -11,7 +11,6 @@
  */
 
 #include "qemu-common.h"
-#include "sysemu.h"
 #include "hw/hw.h"
 #include "exec-all.h"
 #include "gdbstub.h"
diff --git a/migration-exec.c b/migration-exec.c
index 14718dd..4b7aad8 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -17,7 +17,6 @@
 #include "qemu_socket.h"
 #include "migration.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "buffered_file.h"
 #include "block.h"
 #include <sys/types.h>
diff --git a/migration-fd.c b/migration-fd.c
index 6d14505..66d51c1 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -16,7 +16,6 @@
 #include "migration.h"
 #include "monitor.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "buffered_file.h"
 #include "block.h"
 #include "qemu_socket.h"
diff --git a/migration-tcp.c b/migration-tcp.c
index e8dff9d..d3d80c9 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -15,7 +15,6 @@
 #include "qemu_socket.h"
 #include "migration.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "buffered_file.h"
 #include "block.h"
 
diff --git a/migration-unix.c b/migration-unix.c
index 8b967f2..c8625c7 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -15,7 +15,6 @@
 #include "qemu_socket.h"
 #include "migration.h"
 #include "qemu-char.h"
-#include "sysemu.h"
 #include "buffered_file.h"
 #include "block.h"
 
diff --git a/net.c b/net.c
index 8d6a555..4f777c3 100644
--- a/net.c
+++ b/net.c
@@ -32,7 +32,6 @@
 #include "net/vde.h"
 #include "net/util.h"
 #include "monitor.h"
-#include "sysemu.h"
 #include "qemu-common.h"
 #include "qemu_socket.h"
 #include "hw/qdev.h"
diff --git a/net/slirp.c b/net/slirp.c
index b41c60a..e387a11 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -30,7 +30,6 @@
 #endif
 #include "net.h"
 #include "monitor.h"
-#include "sysemu.h"
 #include "qemu_socket.h"
 #include "slirp/libslirp.h"
 
diff --git a/net/vde.c b/net/vde.c
index 0b46fa6..ac48ab2 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -31,7 +31,6 @@
 #include "qemu-char.h"
 #include "qemu-common.h"
 #include "qemu-option.h"
-#include "sysemu.h"
 
 typedef struct VDEState {
     VLANClientState nc;
diff --git a/osdep.c b/osdep.c
index 327583b..56e6963 100644
--- a/osdep.c
+++ b/osdep.c
@@ -46,7 +46,6 @@ extern int madvise(caddr_t, size_t, int);
 
 #include "qemu-common.h"
 #include "trace.h"
-#include "sysemu.h"
 #include "qemu_socket.h"
 
 int qemu_madvise(void *addr, size_t len, int advice)
diff --git a/qemu-config.c b/qemu-config.c
index 323d3c2..14d3419 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -2,7 +2,6 @@
 #include "qemu-error.h"
 #include "qemu-option.h"
 #include "qemu-config.h"
-#include "sysemu.h"
 #include "hw/qdev.h"
 
 static QemuOptsList qemu_drive_opts = {
diff --git a/qemu-error.c b/qemu-error.c
index 5a35e7c..41c191d 100644
--- a/qemu-error.c
+++ b/qemu-error.c
@@ -12,7 +12,6 @@
 
 #include <stdio.h>
 #include "monitor.h"
-#include "sysemu.h"
 
 /*
  * Print to current monitor if we have one, else to stderr.
diff --git a/qemu-tool.c b/qemu-tool.c
index d45840d..f4a6ad0 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -15,7 +15,6 @@
 #include "monitor.h"
 #include "qemu-timer.h"
 #include "qemu-log.h"
-#include "sysemu.h"
 
 #include <sys/time.h>
 
commit 33d05394a6f5e7923bc115faf5122b7f38b0418a
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 27 09:07:54 2011 +0000

    json-lexer: fix conflict with mingw32 ERROR definition
    
    The name ERROR is too generic, it conflicts with mingw32 ERROR definition.
    
    Replace ERROR with IN_ERROR.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/json-lexer.c b/json-lexer.c
index c736f42..65c9720 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -28,7 +28,7 @@
  */
 
 enum json_lexer_state {
-    ERROR = 0,
+    IN_ERROR = 0,
     IN_DQ_UCODE3,
     IN_DQ_UCODE2,
     IN_DQ_UCODE1,
@@ -150,7 +150,7 @@ static const uint8_t json_lexer[][256] =  {
     /* Zero */
     [IN_ZERO] = {
         TERMINAL(JSON_INTEGER),
-        ['0' ... '9'] = ERROR,
+        ['0' ... '9'] = IN_ERROR,
         ['.'] = IN_MANTISSA,
     },
 
@@ -302,7 +302,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch)
             lexer->token = qstring_new();
             new_state = IN_START;
             break;
-        case ERROR:
+        case IN_ERROR:
             return -EINVAL;
         default:
             break;
commit 1a00282a739d5cb7247ac3634ddd3e76537ef5eb
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Apr 14 19:19:00 2011 +0200

    sparc: Fix assertion caused by empty memory slot with 0 byte
    
    If the memory size given on the command line is equal to the
    maximum size of memory defined by the hardware, there is no
    "empty slot" after physical memory.
    
    The following command
    
    		qemu-system-sparc -m 256
    
    raised an assertion:
    exec.c:2614: cpu_register_physical_memory_offset: Assertion `size' failed
    
    This can be fixed either at the caller side (don't call empty_slot_init)
    or in empty_slot_init (do nothing) when size == 0. The second solution
    was choosen here because it is more robust.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>

diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 664b8d9..da8adc4 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -53,18 +53,21 @@ static CPUWriteMemoryFunc * const empty_slot_write[3] = {
 
 void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
 {
-    DeviceState *dev;
-    SysBusDevice *s;
-    EmptySlot *e;
+    if (slot_size > 0) {
+        /* Only empty slots larger than 0 byte need handling. */
+        DeviceState *dev;
+        SysBusDevice *s;
+        EmptySlot *e;
 
-    dev = qdev_create(NULL, "empty_slot");
-    s = sysbus_from_qdev(dev);
-    e = FROM_SYSBUS(EmptySlot, s);
-    e->size = slot_size;
+        dev = qdev_create(NULL, "empty_slot");
+        s = sysbus_from_qdev(dev);
+        e = FROM_SYSBUS(EmptySlot, s);
+        e->size = slot_size;
 
-    qdev_init_nofail(dev);
+        qdev_init_nofail(dev);
 
-    sysbus_mmio_map(s, 0, addr);
+        sysbus_mmio_map(s, 0, addr);
+    }
 }
 
 static int empty_slot_init1(SysBusDevice *dev)
commit cb842c90a485d9dbf05fa51e1500b3c1a1931256
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 13 10:03:46 2011 +0200

    qemu_next_deadline should not consider host-time timers
    
    It is purely for icount-based virtual timers.  And now that we got the
    code right, rename the function to clarify the intended scope.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/cpus.c b/cpus.c
index 6a50199..1fc34b7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -833,7 +833,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     while (1) {
         cpu_exec_all();
-        if (use_icount && qemu_next_deadline() <= 0) {
+        if (use_icount && qemu_next_icount_deadline() <= 0) {
             qemu_notify_event();
         }
         qemu_tcg_wait_io_event();
@@ -1050,7 +1050,7 @@ static int tcg_cpu_exec(CPUState *env)
         qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
         env->icount_decr.u16.low = 0;
         env->icount_extra = 0;
-        count = qemu_icount_round (qemu_next_deadline());
+        count = qemu_icount_round(qemu_next_icount_deadline());
         qemu_icount += count;
         decr = (count > 0xffff) ? 0xffff : count;
         count -= decr;
diff --git a/qemu-timer.c b/qemu-timer.c
index 7998f37..b8c0c88 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -452,7 +452,7 @@ void qemu_clock_warp(QEMUClock *clock)
     }
 
     vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
-    deadline = qemu_next_deadline();
+    deadline = qemu_next_icount_deadline();
     if (deadline > 0) {
         /*
          * Ensure the vm_clock proceeds even when the virtual CPU goes to
@@ -765,21 +765,16 @@ static void host_alarm_handler(int host_signum)
     }
 }
 
-int64_t qemu_next_deadline(void)
+int64_t qemu_next_icount_deadline(void)
 {
     /* To avoid problems with overflow limit this to 2^32.  */
     int64_t delta = INT32_MAX;
 
+    assert(use_icount);
     if (active_timers[QEMU_CLOCK_VIRTUAL]) {
         delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
                      qemu_get_clock_ns(vm_clock);
     }
-    if (active_timers[QEMU_CLOCK_HOST]) {
-        int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
-                 qemu_get_clock_ns(host_clock);
-        if (hdelta < delta)
-            delta = hdelta;
-    }
 
     if (delta < 0)
         delta = 0;
@@ -1169,7 +1164,7 @@ int qemu_calculate_timeout(void)
         } else {
             /* Wait for either IO to occur or the next
                timer event.  */
-            add = qemu_next_deadline();
+            add = qemu_next_icount_deadline();
             /* We advance the timer before checking for IO.
                Limit the amount we advance so that early IO
                activity won't get the guest too far ahead.  */
diff --git a/qemu-timer.h b/qemu-timer.h
index c01bcab..3a9228f 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -51,7 +51,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
 
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
-int64_t qemu_next_deadline(void);
+int64_t qemu_next_icount_deadline(void);
 void configure_alarms(char const *opt);
 void configure_icount(const char *option);
 int qemu_calculate_timeout(void);
commit 1ece93a91b8435b815ce7214cf41bbbbe7929e8b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 13 10:03:45 2011 +0200

    Revert wrong fixes for -icount in the iothread case
    
    This reverts commits 225d02cd and c9f7383c.  While some parts of
    the latter could be saved, I preferred a smooth, complete revert.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 4959688..7998f37 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -110,9 +110,12 @@ static int64_t cpu_get_clock(void)
     }
 }
 
+#ifndef CONFIG_IOTHREAD
 static int64_t qemu_icount_delta(void)
 {
-    if (use_icount == 1) {
+    if (!use_icount) {
+        return 5000 * (int64_t) 1000000;
+    } else if (use_icount == 1) {
         /* When not using an adaptive execution frequency
            we tend to get badly out of sync with real time,
            so just delay for a reasonable amount of time.  */
@@ -121,6 +124,7 @@ static int64_t qemu_icount_delta(void)
         return cpu_get_icount() - cpu_get_clock();
     }
 }
+#endif
 
 /* enable cpu_get_ticks() */
 void cpu_enable_ticks(void)
@@ -1147,39 +1151,41 @@ void quit_timers(void)
 
 int qemu_calculate_timeout(void)
 {
+#ifndef CONFIG_IOTHREAD
     int timeout;
-    int64_t add;
-    int64_t delta;
 
-    /* When using icount, making forward progress with qemu_icount when the
-       guest CPU is idle is critical. We only use the static io-thread timeout
-       for non icount runs.  */
-    if (!use_icount || !vm_running) {
-        return 5000;
-    }
-
-    /* Advance virtual time to the next event.  */
-    delta = qemu_icount_delta();
-    if (delta > 0) {
-        /* If virtual time is ahead of real time then just
-           wait for IO.  */
-        timeout = (delta + 999999) / 1000000;
-    } else {
-        /* Wait for either IO to occur or the next
-           timer event.  */
-        add = qemu_next_deadline();
-        /* We advance the timer before checking for IO.
-           Limit the amount we advance so that early IO
-           activity won't get the guest too far ahead.  */
-        if (add > 10000000)
-            add = 10000000;
-        delta += add;
-        qemu_icount += qemu_icount_round (add);
-        timeout = delta / 1000000;
-        if (timeout < 0)
-            timeout = 0;
+    if (!vm_running)
+        timeout = 5000;
+    else {
+     /* XXX: use timeout computed from timers */
+        int64_t add;
+        int64_t delta;
+        /* Advance virtual time to the next event.  */
+	delta = qemu_icount_delta();
+        if (delta > 0) {
+            /* If virtual time is ahead of real time then just
+               wait for IO.  */
+            timeout = (delta + 999999) / 1000000;
+        } else {
+            /* Wait for either IO to occur or the next
+               timer event.  */
+            add = qemu_next_deadline();
+            /* We advance the timer before checking for IO.
+               Limit the amount we advance so that early IO
+               activity won't get the guest too far ahead.  */
+            if (add > 10000000)
+                add = 10000000;
+            delta += add;
+            qemu_icount += qemu_icount_round (add);
+            timeout = delta / 1000000;
+            if (timeout < 0)
+                timeout = 0;
+        }
     }
 
     return timeout;
+#else /* CONFIG_IOTHREAD */
+    return 1000;
+#endif
 }
 
commit ab33fcda9f96b9195dfb3fcf5bd9bb5383caeaea
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 13 10:03:44 2011 +0200

    enable vm_clock to "warp" in the iothread+icount case
    
    The previous patch however is not enough, because if the virtual CPU
    goes to sleep waiting for a future timer interrupt to wake it up, qemu
    deadlocks.  The timer interrupt never comes because time is driven by
    icount, but the vCPU doesn't run any insns.
    
    You could say that VCPUs should never go to sleep in icount
    mode if there is a pending vm_clock timer; rather time should
    just warp to the next vm_clock event with no sleep ever taking place.
    Even better, you can sleep for some time related to the
    time left until the next event, to avoid that the warps are too visible
    externally; for example, you could be sending network packets continously
    instead of every 100ms.
    
    This is what this patch implements.  qemu_clock_warp is called: 1)
    whenever a vm_clock timer is adjusted, to ensure the warp_timer is
    synchronized; 2) at strategic points in the CPU thread, to make sure
    the insn counter is synchronized before the CPU starts running.
    In any case, the warp_timer is disabled while the CPU is running,
    because the insn counter will then be making progress on its own.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/cpus.c b/cpus.c
index cbeac7a..6a50199 100644
--- a/cpus.c
+++ b/cpus.c
@@ -155,7 +155,7 @@ static bool cpu_thread_is_idle(CPUState *env)
     return true;
 }
 
-static bool all_cpu_threads_idle(void)
+bool all_cpu_threads_idle(void)
 {
     CPUState *env;
 
@@ -739,6 +739,9 @@ static void qemu_tcg_wait_io_event(void)
     CPUState *env;
 
     while (all_cpu_threads_idle()) {
+       /* Start accounting real time to the virtual clock if the CPUs
+          are idle.  */
+        qemu_clock_warp(vm_clock);
         qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
     }
 
@@ -1073,6 +1076,9 @@ bool cpu_exec_all(void)
 {
     int r;
 
+    /* Account partial waits to the vm_clock.  */
+    qemu_clock_warp(vm_clock);
+
     if (next_cpu == NULL) {
         next_cpu = first_cpu;
     }
diff --git a/qemu-common.h b/qemu-common.h
index 82e27c1..4f6037b 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -298,6 +298,7 @@ void qemu_notify_event(void);
 void qemu_cpu_kick(void *env);
 void qemu_cpu_kick_self(void);
 int qemu_cpu_is_self(void *env);
+bool all_cpu_threads_idle(void);
 
 /* work queue */
 struct qemu_work_item {
diff --git a/qemu-timer.c b/qemu-timer.c
index 50f1943..4959688 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -153,6 +153,8 @@ void cpu_disable_ticks(void)
 struct QEMUClock {
     int type;
     int enabled;
+
+    QEMUTimer *warp_timer;
 };
 
 struct QEMUTimer {
@@ -386,6 +388,90 @@ void qemu_clock_enable(QEMUClock *clock, int enabled)
     clock->enabled = enabled;
 }
 
+static int64_t vm_clock_warp_start;
+
+static void icount_warp_rt(void *opaque)
+{
+    if (vm_clock_warp_start == -1) {
+        return;
+    }
+
+    if (vm_running) {
+        int64_t clock = qemu_get_clock_ns(rt_clock);
+        int64_t warp_delta = clock - vm_clock_warp_start;
+        if (use_icount == 1) {
+            qemu_icount_bias += warp_delta;
+        } else {
+            /*
+             * In adaptive mode, do not let the vm_clock run too
+             * far ahead of real time.
+             */
+            int64_t cur_time = cpu_get_clock();
+            int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+            int64_t delta = cur_time - cur_icount;
+            qemu_icount_bias += MIN(warp_delta, delta);
+        }
+        if (qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
+                               qemu_get_clock_ns(vm_clock))) {
+            qemu_notify_event();
+        }
+    }
+    vm_clock_warp_start = -1;
+}
+
+void qemu_clock_warp(QEMUClock *clock)
+{
+    int64_t deadline;
+
+    if (!clock->warp_timer) {
+        return;
+    }
+
+    /*
+     * There are too many global variables to make the "warp" behavior
+     * applicable to other clocks.  But a clock argument removes the
+     * need for if statements all over the place.
+     */
+    assert(clock == vm_clock);
+
+    /*
+     * If the CPUs have been sleeping, advance the vm_clock timer now.  This
+     * ensures that the deadline for the timer is computed correctly below.
+     * This also makes sure that the insn counter is synchronized before the
+     * CPU starts running, in case the CPU is woken by an event other than
+     * the earliest vm_clock timer.
+     */
+    icount_warp_rt(NULL);
+    if (!all_cpu_threads_idle() || !active_timers[clock->type]) {
+        qemu_del_timer(clock->warp_timer);
+        return;
+    }
+
+    vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
+    deadline = qemu_next_deadline();
+    if (deadline > 0) {
+        /*
+         * Ensure the vm_clock proceeds even when the virtual CPU goes to
+         * sleep.  Otherwise, the CPU might be waiting for a future timer
+         * interrupt to wake it up, but the interrupt never comes because
+         * the vCPU isn't running any insns and thus doesn't advance the
+         * vm_clock.
+         *
+         * An extreme solution for this problem would be to never let VCPUs
+         * sleep in icount mode if there is a pending vm_clock timer; rather
+         * time could just advance to the next vm_clock event.  Instead, we
+         * do stop VCPUs and only advance vm_clock after some "real" time,
+         * (related to the time left until the next event) has passed.  This
+         * rt_clock timer will do this.  This avoids that the warps are too
+         * visible externally---for example, you will not be sending network
+         * packets continously instead of every 100ms.
+         */
+        qemu_mod_timer(clock->warp_timer, vm_clock_warp_start + deadline);
+    } else {
+        qemu_notify_event();
+    }
+}
+
 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque)
 {
@@ -454,8 +540,10 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
             qemu_rearm_alarm_timer(alarm_timer);
         }
         /* Interrupt execution to force deadline recalculation.  */
-        if (use_icount)
+        qemu_clock_warp(ts->clock);
+        if (use_icount) {
             qemu_notify_event();
+        }
     }
 }
 
@@ -576,6 +664,10 @@ void configure_icount(const char *option)
     if (!option)
         return;
 
+#ifdef CONFIG_IOTHREAD
+    vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+#endif
+
     if (strcmp(option, "auto") != 0) {
         icount_time_shift = strtol(option, NULL, 0);
         use_icount = 1;
diff --git a/qemu-timer.h b/qemu-timer.h
index 75d5675..c01bcab 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -39,6 +39,7 @@ extern QEMUClock *host_clock;
 
 int64_t qemu_get_clock_ns(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
+void qemu_clock_warp(QEMUClock *clock);
 
 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque);
commit 3b2319a30b5ae528787bf3769b1a28a863b53252
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 13 10:03:43 2011 +0200

    really fix -icount in the iothread case
    
    The correct fix for -icount is to consider the biggest difference
    between iothread and non-iothread modes.  In the traditional model,
    CPUs run _before_ the iothread calls select (or WaitForMultipleObjects
    for Win32).  In the iothread model, CPUs run while the iothread
    isn't holding the mutex, i.e. _during_ those same calls.
    
    So, the iothread should always block as long as possible to let
    the CPUs run smoothly---the timeout might as well be infinite---and
    either the OS or the CPU thread itself will let the iothread know
    when something happens.  At this point, the iothread wakes up and
    interrupts the CPU.
    
    This is exactly the approach that this patch takes: when cpu_exec_all
    returns in -icount mode, and it is because a vm_clock deadline has
    been met, it wakes up the iothread to process the timers.  This is
    really the "bulk" of fixing icount.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/cpus.c b/cpus.c
index 41bec7c..cbeac7a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -830,6 +830,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     while (1) {
         cpu_exec_all();
+        if (use_icount && qemu_next_deadline() <= 0) {
+            qemu_notify_event();
+        }
         qemu_tcg_wait_io_event();
     }
 
commit 420b6c317de87890e06225de6e2f8af7bf714df0
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 14 14:11:56 2011 +0100

    tests/test-mmap.c: Check mmap() return value before using it
    
    Correct the position of a "stop if MAP_FAILED" check in the mmap()
    tests, so that if mmap() does fail we print a failure message
    rather than segfaulting inside memcpy().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/tests/test-mmap.c b/tests/test-mmap.c
index fcb365f..c578e25 100644
--- a/tests/test-mmap.c
+++ b/tests/test-mmap.c
@@ -164,6 +164,7 @@ void check_aligned_anonymous_unfixed_colliding_mmaps(void)
 		nlen = pagesize * 8;
 		p3 = mmap(NULL, nlen, PROT_READ, 
 			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		fail_unless (p3 != MAP_FAILED);
 
 		/* Check if the mmaped areas collide.  */
 		if (p3 < p2 
@@ -174,7 +175,6 @@ void check_aligned_anonymous_unfixed_colliding_mmaps(void)
 
 		/* Make sure we get pages aligned with the pagesize. The
 		   target expects this.  */
-		fail_unless (p3 != MAP_FAILED);
 		p = (uintptr_t) p3;
 		fail_unless ((p & pagemask) == 0);
 		munmap (p2, pagesize);
commit 4d9ad7f793605abd9806fc932b3e04e028894565
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:32:08 2011 +0100

    target-arm: Don't overflow when calculating value for signed VABAL
    
    In the VABAL instruction we take the absolute difference of two
    values of size x and store it in a result of size 2x. This means
    we have to be careful to calculate the absolute difference using
    a wide enough type that we don't accidentally overflow.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index c3ac96a..7df925a 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1514,9 +1514,13 @@ uint64_t HELPER(neon_addl_saturate_s64)(uint64_t a, uint64_t b)
     return result;
 }
 
-#define DO_ABD(dest, x, y, type) do { \
-    type tmp_x = x; \
-    type tmp_y = y; \
+/* We have to do the arithmetic in a larger type than
+ * the input type, because for example with a signed 32 bit
+ * op the absolute difference can overflow a signed 32 bit value.
+ */
+#define DO_ABD(dest, x, y, intype, arithtype) do {            \
+    arithtype tmp_x = (intype)(x);                            \
+    arithtype tmp_y = (intype)(y);                            \
     dest = ((tmp_x > tmp_y) ? tmp_x - tmp_y : tmp_y - tmp_x); \
     } while(0)
 
@@ -1524,12 +1528,12 @@ uint64_t HELPER(neon_abdl_u16)(uint32_t a, uint32_t b)
 {
     uint64_t tmp;
     uint64_t result;
-    DO_ABD(result, a, b, uint8_t);
-    DO_ABD(tmp, a >> 8, b >> 8, uint8_t);
+    DO_ABD(result, a, b, uint8_t, uint32_t);
+    DO_ABD(tmp, a >> 8, b >> 8, uint8_t, uint32_t);
     result |= tmp << 16;
-    DO_ABD(tmp, a >> 16, b >> 16, uint8_t);
+    DO_ABD(tmp, a >> 16, b >> 16, uint8_t, uint32_t);
     result |= tmp << 32;
-    DO_ABD(tmp, a >> 24, b >> 24, uint8_t);
+    DO_ABD(tmp, a >> 24, b >> 24, uint8_t, uint32_t);
     result |= tmp << 48;
     return result;
 }
@@ -1538,12 +1542,12 @@ uint64_t HELPER(neon_abdl_s16)(uint32_t a, uint32_t b)
 {
     uint64_t tmp;
     uint64_t result;
-    DO_ABD(result, a, b, int8_t);
-    DO_ABD(tmp, a >> 8, b >> 8, int8_t);
+    DO_ABD(result, a, b, int8_t, int32_t);
+    DO_ABD(tmp, a >> 8, b >> 8, int8_t, int32_t);
     result |= tmp << 16;
-    DO_ABD(tmp, a >> 16, b >> 16, int8_t);
+    DO_ABD(tmp, a >> 16, b >> 16, int8_t, int32_t);
     result |= tmp << 32;
-    DO_ABD(tmp, a >> 24, b >> 24, int8_t);
+    DO_ABD(tmp, a >> 24, b >> 24, int8_t, int32_t);
     result |= tmp << 48;
     return result;
 }
@@ -1552,8 +1556,8 @@ uint64_t HELPER(neon_abdl_u32)(uint32_t a, uint32_t b)
 {
     uint64_t tmp;
     uint64_t result;
-    DO_ABD(result, a, b, uint16_t);
-    DO_ABD(tmp, a >> 16, b >> 16, uint16_t);
+    DO_ABD(result, a, b, uint16_t, uint32_t);
+    DO_ABD(tmp, a >> 16, b >> 16, uint16_t, uint32_t);
     return result | (tmp << 32);
 }
 
@@ -1561,22 +1565,22 @@ uint64_t HELPER(neon_abdl_s32)(uint32_t a, uint32_t b)
 {
     uint64_t tmp;
     uint64_t result;
-    DO_ABD(result, a, b, int16_t);
-    DO_ABD(tmp, a >> 16, b >> 16, int16_t);
+    DO_ABD(result, a, b, int16_t, int32_t);
+    DO_ABD(tmp, a >> 16, b >> 16, int16_t, int32_t);
     return result | (tmp << 32);
 }
 
 uint64_t HELPER(neon_abdl_u64)(uint32_t a, uint32_t b)
 {
     uint64_t result;
-    DO_ABD(result, a, b, uint32_t);
+    DO_ABD(result, a, b, uint32_t, uint64_t);
     return result;
 }
 
 uint64_t HELPER(neon_abdl_s64)(uint32_t a, uint32_t b)
 {
     uint64_t result;
-    DO_ABD(result, a, b, int32_t);
+    DO_ABD(result, a, b, int32_t, int64_t);
     return result;
 }
 #undef DO_ABD
commit cc9453f457888bdd3ab7b37988adbfc4712fa125
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 13 08:16:53 2011 -0500

    Revert SeaBIOS change due to overzealous commit -a
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/roms/seabios b/roms/seabios
index 06d0bdd..cc97564 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4
+Subproject commit cc975646af69f279396d4d5e1379ac6af80ee637
commit 7f7454ec296b3403b4accec55349a8f0232d3576
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 13 07:41:19 2011 -0500

    lm32: fix build breakage due to uninitialized variable 'r'
    
    gcc 4.5.2 correctly complains that r is potentially uninitialized in this
    function.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index 4831e00..94e6315 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -163,7 +163,7 @@ static int pfpu_decode_insn(MilkymistPFPUState *s)
     uint32_t reg_b = (insn >> 11) & 0x7f;
     uint32_t op = (insn >> 7) & 0xf;
     uint32_t reg_d = insn & 0x7f;
-    uint32_t r;
+    uint32_t r = 0;
     int latency = 0;
 
     switch (op) {
diff --git a/roms/seabios b/roms/seabios
index cc97564..06d0bdd 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit cc975646af69f279396d4d5e1379ac6af80ee637
+Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4
commit 2d56a546a73ca3f588196f4065621ff5f11f50e4
Author: Mitnick Lyu <mitnick.lyu at gmail.com>
Date:   Wed Apr 13 17:30:54 2011 +0800

    vpc.c: Use get_option_parameter() does the search
    
    Use get_option_parameter() to instead of duplicating the loop, and
    use BDRV_SECTOR_SIZE to instead of 512
    
    Signed-off-by: Mitnick Lyu <mitnick.lyu at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index 7b025be..56865da 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -505,12 +505,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     int ret = -EIO;
 
     // Read out options
-    while (options && options->name) {
-        if (!strcmp(options->name, "size")) {
-            total_sectors = options->value.n / 512;
-        }
-        options++;
-    }
+    total_sectors = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n /
+                    BDRV_SECTOR_SIZE;
 
     // Create the file
     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
commit 996faf1ad4a93342e381766d95686b16624f0dbd
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 12 21:36:07 2011 +0530

    atapi: GESN: implement 'media' subcommand
    
    Implement the 'media' sub-command of the GET_EVENT_STATUS_NOTIFICATION
    command.  This helps us report tray open, tray closed, no media, media
    present states to the guest.
    
    Newer Linux kernels (2.6.38+) rely on this command to revalidate discs
    after media change.
    
    This patch also sends out tray open/closed status to the guest driver
    when requested e.g. via the CDROM_DRIVE_STATUS ioctl (thanks Markus).
    Without such notification, the guest and qemu's tray open/close status
    was frequently out of sync, causing installers like Anaconda detecting
    no disc instead of tray open, confusing them terribly.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index a38cc14..f028ddb 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1084,6 +1084,48 @@ static int ide_dvd_read_structure(IDEState *s, int format,
     }
 }
 
+static unsigned int event_status_media(IDEState *s,
+                                       uint8_t *buf)
+{
+    enum media_event_code {
+        MEC_NO_CHANGE = 0,       /* Status unchanged */
+        MEC_EJECT_REQUESTED,     /* received a request from user to eject */
+        MEC_NEW_MEDIA,           /* new media inserted and ready for access */
+        MEC_MEDIA_REMOVAL,       /* only for media changers */
+        MEC_MEDIA_CHANGED,       /* only for media changers */
+        MEC_BG_FORMAT_COMPLETED, /* MRW or DVD+RW b/g format completed */
+        MEC_BG_FORMAT_RESTARTED, /* MRW or DVD+RW b/g format restarted */
+    };
+    enum media_status {
+        MS_TRAY_OPEN = 1,
+        MS_MEDIA_PRESENT = 2,
+    };
+    uint8_t event_code, media_status;
+
+    media_status = 0;
+    if (s->bs->tray_open) {
+        media_status = MS_TRAY_OPEN;
+    } else if (bdrv_is_inserted(s->bs)) {
+        media_status = MS_MEDIA_PRESENT;
+    }
+
+    /* Event notification descriptor */
+    event_code = MEC_NO_CHANGE;
+    if (media_status != MS_TRAY_OPEN && s->events.new_media) {
+        event_code = MEC_NEW_MEDIA;
+        s->events.new_media = false;
+    }
+
+    buf[4] = event_code;
+    buf[5] = media_status;
+
+    /* These fields are reserved, just clear them. */
+    buf[6] = 0;
+    buf[7] = 0;
+
+    return 8; /* We wrote to 4 extra bytes from the header */
+}
+
 static void handle_get_event_status_notification(IDEState *s,
                                                  uint8_t *buf,
                                                  const uint8_t *packet)
@@ -1104,6 +1146,26 @@ static void handle_get_event_status_notification(IDEState *s,
         uint8_t supported_events;
     } __attribute((packed)) *gesn_event_header;
 
+    enum notification_class_request_type {
+        NCR_RESERVED1 = 1 << 0,
+        NCR_OPERATIONAL_CHANGE = 1 << 1,
+        NCR_POWER_MANAGEMENT = 1 << 2,
+        NCR_EXTERNAL_REQUEST = 1 << 3,
+        NCR_MEDIA = 1 << 4,
+        NCR_MULTI_HOST = 1 << 5,
+        NCR_DEVICE_BUSY = 1 << 6,
+        NCR_RESERVED2 = 1 << 7,
+    };
+    enum event_notification_class_field {
+        ENC_NO_EVENTS = 0,
+        ENC_OPERATIONAL_CHANGE,
+        ENC_POWER_MANAGEMENT,
+        ENC_EXTERNAL_REQUEST,
+        ENC_MEDIA,
+        ENC_MULTIPLE_HOSTS,
+        ENC_DEVICE_BUSY,
+        ENC_RESERVED,
+    };
     unsigned int max_len, used_len;
 
     gesn_cdb = (void *)packet;
@@ -1121,12 +1183,32 @@ static void handle_get_event_status_notification(IDEState *s,
 
     /* polling mode operation */
 
-    /* We don't support any event class (yet). */
-    gesn_event_header->supported_events = 0;
+    /*
+     * These are the supported events.
+     *
+     * We currently only support requests of the 'media' type.
+     */
+    gesn_event_header->supported_events = NCR_MEDIA;
 
-    gesn_event_header->notification_class = 0x80; /* No event available */
-    used_len = sizeof(*gesn_event_header);
+    /*
+     * We use |= below to set the class field; other bits in this byte
+     * are reserved now but this is useful to do if we have to use the
+     * reserved fields later.
+     */
+    gesn_event_header->notification_class = 0;
 
+    /*
+     * Responses to requests are to be based on request priority.  The
+     * notification_class_request_type enum above specifies the
+     * priority: upper elements are higher prio than lower ones.
+     */
+    if (gesn_cdb->class & NCR_MEDIA) {
+        gesn_event_header->notification_class |= ENC_MEDIA;
+        used_len = event_status_media(s, buf);
+    } else {
+        gesn_event_header->notification_class = 0x80; /* No event available */
+        used_len = sizeof(*gesn_event_header);
+    }
     gesn_event_header->len = cpu_to_be16(used_len
                                          - sizeof(*gesn_event_header));
     ide_atapi_cmd_reply(s, used_len, max_len);
@@ -1655,6 +1737,7 @@ static void cdrom_change_cb(void *opaque, int reason)
     s->sense_key = SENSE_UNIT_ATTENTION;
     s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
     s->cdrom_changed = 1;
+    s->events.new_media = true;
     ide_set_irq(s->bus);
 }
 
@@ -2799,6 +2882,25 @@ static bool ide_drive_pio_state_needed(void *opaque)
     return (s->status & DRQ_STAT) != 0;
 }
 
+static bool ide_atapi_gesn_needed(void *opaque)
+{
+    IDEState *s = opaque;
+
+    return s->events.new_media || s->events.eject_request;
+}
+
+/* Fields for GET_EVENT_STATUS_NOTIFICATION ATAPI command */
+const VMStateDescription vmstate_ide_atapi_gesn_state = {
+    .name ="ide_drive/atapi/gesn_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_BOOL(events.new_media, IDEState),
+        VMSTATE_BOOL(events.eject_request, IDEState),
+    }
+};
+
 const VMStateDescription vmstate_ide_drive_pio_state = {
     .name = "ide_drive/pio_state",
     .version_id = 1,
@@ -2853,6 +2955,9 @@ const VMStateDescription vmstate_ide_drive = {
             .vmsd = &vmstate_ide_drive_pio_state,
             .needed = ide_drive_pio_state_needed,
         }, {
+            .vmsd = &vmstate_ide_atapi_gesn_state,
+            .needed = ide_atapi_gesn_needed,
+        }, {
             /* empty */
         }
     }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index d533fb6..ba7e9a8 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -373,6 +373,11 @@ typedef int DMAFunc(IDEDMA *);
 typedef int DMAIntFunc(IDEDMA *, int);
 typedef void DMARestartFunc(void *, int, int);
 
+struct unreported_events {
+    bool eject_request;
+    bool new_media;
+};
+
 /* NOTE: IDEState represents in fact one drive */
 struct IDEState {
     IDEBus *bus;
@@ -408,6 +413,7 @@ struct IDEState {
     BlockDriverState *bs;
     char version[9];
     /* ATAPI specific */
+    struct unreported_events events;
     uint8_t sense_key;
     uint8_t asc;
     uint8_t cdrom_changed;
commit 0af63ba3629e6f826846a73636ca391a810b2c6e
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 12 21:36:06 2011 +0530

    atapi: GESN: Standardise event response handling for future additions
    
    Handle GET_EVENT_STATUS_NOTIFICATION's No Event Available response in a
    generic way so that future additions to the code to handle other
    response types is easier.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index f976947..a38cc14 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1098,9 +1098,17 @@ static void handle_get_event_status_notification(IDEState *s,
         uint8_t control;
     } __attribute__((packed)) *gesn_cdb;
 
-    unsigned int max_len;
+    struct {
+        uint16_t len;
+        uint8_t notification_class;
+        uint8_t supported_events;
+    } __attribute((packed)) *gesn_event_header;
+
+    unsigned int max_len, used_len;
 
     gesn_cdb = (void *)packet;
+    gesn_event_header = (void *)buf;
+
     max_len = be16_to_cpu(gesn_cdb->len);
 
     /* It is fine by the MMC spec to not support async mode operations */
@@ -1111,12 +1119,17 @@ static void handle_get_event_status_notification(IDEState *s,
         return;
     }
 
-    /* polling */
+    /* polling mode operation */
+
     /* We don't support any event class (yet). */
-    cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
-    buf[2] = 0x80;           /* No Event Available (NEA) */
-    buf[3] = 0x00;           /* Empty supported event classes */
-    ide_atapi_cmd_reply(s, 4, max_len);
+    gesn_event_header->supported_events = 0;
+
+    gesn_event_header->notification_class = 0x80; /* No event available */
+    used_len = sizeof(*gesn_event_header);
+
+    gesn_event_header->len = cpu_to_be16(used_len
+                                         - sizeof(*gesn_event_header));
+    ide_atapi_cmd_reply(s, used_len, max_len);
 }
 
 static void ide_atapi_cmd(IDEState *s)
commit 8f8e834d70216372619b79a10392cdf208bbd3d0
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 12 21:36:05 2011 +0530

    atapi: GESN: Use structs for commonly-used field types
    
    Instead of using magic numbers, use structs that are more descriptive of
    the fields being used.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 4e4ade2..f976947 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1088,11 +1088,23 @@ static void handle_get_event_status_notification(IDEState *s,
                                                  uint8_t *buf,
                                                  const uint8_t *packet)
 {
+    struct {
+        uint8_t opcode;
+        uint8_t polled;        /* lsb bit is polled; others are reserved */
+        uint8_t reserved2[2];
+        uint8_t class;
+        uint8_t reserved3[2];
+        uint16_t len;
+        uint8_t control;
+    } __attribute__((packed)) *gesn_cdb;
+
     unsigned int max_len;
 
-    max_len = ube16_to_cpu(packet + 7);
+    gesn_cdb = (void *)packet;
+    max_len = be16_to_cpu(gesn_cdb->len);
 
-    if (!(packet[1] & 0x01)) { /* asynchronous mode */
+    /* It is fine by the MMC spec to not support async mode operations */
+    if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */
         /* Only polling is supported, asynchronous mode is not. */
         ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
                             ASC_INV_FIELD_IN_CMD_PACKET);
commit 493accd624149e9dcf4b89dcbbdbc42621cbc231
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 12 21:36:04 2011 +0530

    atapi: Move GET_EVENT_STATUS_NOTIFICATION command handling to its own function
    
    This makes the code more readable.
    
    Also, there's a block like:
    
    if () {
      ...
    } else {
      ...
    }
    
    Split that into
    
    if () {
      ...
      return;
    }
    ...
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index f0da95d..4e4ade2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1084,6 +1084,29 @@ static int ide_dvd_read_structure(IDEState *s, int format,
     }
 }
 
+static void handle_get_event_status_notification(IDEState *s,
+                                                 uint8_t *buf,
+                                                 const uint8_t *packet)
+{
+    unsigned int max_len;
+
+    max_len = ube16_to_cpu(packet + 7);
+
+    if (!(packet[1] & 0x01)) { /* asynchronous mode */
+        /* Only polling is supported, asynchronous mode is not. */
+        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                            ASC_INV_FIELD_IN_CMD_PACKET);
+        return;
+    }
+
+    /* polling */
+    /* We don't support any event class (yet). */
+    cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
+    buf[2] = 0x80;           /* No Event Available (NEA) */
+    buf[3] = 0x00;           /* Empty supported event classes */
+    ide_atapi_cmd_reply(s, 4, max_len);
+}
+
 static void ide_atapi_cmd(IDEState *s)
 {
     const uint8_t *packet;
@@ -1529,19 +1552,7 @@ static void ide_atapi_cmd(IDEState *s)
             break;
         }
     case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
-        max_len = ube16_to_cpu(packet + 7);
-
-        if (packet[1] & 0x01) { /* polling */
-            /* We don't support any event class (yet). */
-            cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
-            buf[2] = 0x80;           /* No Event Available (NEA) */
-            buf[3] = 0x00;           /* Empty supported event classes */
-            ide_atapi_cmd_reply(s, 4, max_len);
-        } else { /* asynchronous mode */
-            /* Only polling is supported, asynchronous mode is not. */
-            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
-                                ASC_INV_FIELD_IN_CMD_PACKET);
-        }
+        handle_get_event_status_notification(s, buf, packet);
         break;
     default:
         ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
commit 0c370a35498bf9e300a035864bee7ce8460da669
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 12 21:36:03 2011 +0530

    atapi: Allow GET_EVENT_STATUS_NOTIFICATION after media change
    
    After a media change, the only commands allowed from the guest were
    REQUEST_SENSE and INQUIRY.  The guest may also issue
    GET_EVENT_STATUS_NOTIFICATION commands to get media
    changed notification.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index b5de22e..f0da95d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1102,13 +1102,21 @@ static void ide_atapi_cmd(IDEState *s)
         printf("\n");
     }
 #endif
-    /* If there's a UNIT_ATTENTION condition pending, only
-       REQUEST_SENSE and INQUIRY commands are allowed to complete. */
+    /*
+     * If there's a UNIT_ATTENTION condition pending, only
+     * REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and
+     * GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete.
+     * MMC-5, section 4.1.6.1 lists only these commands being allowed
+     * to complete, with other commands getting a CHECK condition
+     * response unless a higher priority status, defined by the drive
+     * here, is pending.
+     */
     if (s->sense_key == SENSE_UNIT_ATTENTION &&
-	s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
-	s->io_buffer[0] != GPCMD_INQUIRY) {
-	ide_atapi_cmd_check_status(s);
-	return;
+        s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
+        s->io_buffer[0] != GPCMD_INQUIRY &&
+        s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) {
+        ide_atapi_cmd_check_status(s);
+        return;
     }
     switch(s->io_buffer[0]) {
     case GPCMD_TEST_UNIT_READY:
commit 88f2bb58ef97ca269b29fe92bb4834f5ddbcde80
Author: Amit Shah <amit.shah at redhat.com>
Date:   Sat Apr 9 15:54:39 2011 +0530

    atapi: Report correct errors on guest eject request
    
    Table 629 of the MMC-5 spec mentions two different error conditions when
    a CDROM eject is requested: a) while a disc is inserted and b) while a
    disc is not inserted.
    
    Ensure we return the appropriate error for the present condition of the
    drive and disc status.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index a290142..b5de22e 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1304,7 +1304,7 @@ static void ide_atapi_cmd(IDEState *s)
         break;
     case GPCMD_START_STOP_UNIT:
         {
-            int start, eject, err = 0;
+            int start, eject, sense, err = 0;
             start = packet[4] & 1;
             eject = (packet[4] >> 1) & 1;
 
@@ -1317,7 +1317,11 @@ static void ide_atapi_cmd(IDEState *s)
                 ide_atapi_cmd_ok(s);
                 break;
             case -EBUSY:
-                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                sense = SENSE_NOT_READY;
+                if (bdrv_is_inserted(s->bs)) {
+                    sense = SENSE_ILLEGAL_REQUEST;
+                }
+                ide_atapi_cmd_error(s, sense,
                                     ASC_MEDIA_REMOVAL_PREVENTED);
                 break;
             default:
commit 8aa71917f7be78151cff50b850a25f26de614b13
Author: Amit Shah <amit.shah at redhat.com>
Date:   Sat Apr 9 15:54:38 2011 +0530

    atapi: Drives can be locked without media present
    
    Drivers are free to lock drives without any media present.  Such a
    condition should not result in an error condition.
    
    See Table 341 in MMC-5 spec for details.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c11d457..a290142 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1230,13 +1230,8 @@ static void ide_atapi_cmd(IDEState *s)
         ide_atapi_cmd_reply(s, 18, max_len);
         break;
     case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
-        if (bdrv_is_inserted(s->bs)) {
-            bdrv_set_locked(s->bs, packet[4] & 1);
-            ide_atapi_cmd_ok(s);
-        } else {
-            ide_atapi_cmd_error(s, SENSE_NOT_READY,
-                                ASC_MEDIUM_NOT_PRESENT);
-        }
+        bdrv_set_locked(s->bs, packet[4] & 1);
+        ide_atapi_cmd_ok(s);
         break;
     case GPCMD_READ_10:
     case GPCMD_READ_12:
commit 21df65b6444858ddee3a86d8666571bb41695614
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Dec 17 15:58:22 2010 +0000

    qed: Add support for zero clusters
    
    Zero clusters are similar to unallocated clusters except instead of reading
    their value from a backing file when one is available, the cluster is always
    read as zero.
    
    This implements read support only.  At this stage, QED will never write a
    zero cluster.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed-check.c b/block/qed-check.c
index 4600932..ea4ebc8 100644
--- a/block/qed-check.c
+++ b/block/qed-check.c
@@ -72,7 +72,8 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
     for (i = 0; i < s->table_nelems; i++) {
         uint64_t offset = table->offsets[i];
 
-        if (!offset) {
+        if (qed_offset_is_unalloc_cluster(offset) ||
+            qed_offset_is_zero_cluster(offset)) {
             continue;
         }
 
@@ -111,7 +112,7 @@ static int qed_check_l1_table(QEDCheck *check, QEDTable *table)
         unsigned int num_invalid_l2;
         uint64_t offset = table->offsets[i];
 
-        if (!offset) {
+        if (qed_offset_is_unalloc_cluster(offset)) {
             continue;
         }
 
diff --git a/block/qed-cluster.c b/block/qed-cluster.c
index 0ec864b..3e19ad1 100644
--- a/block/qed-cluster.c
+++ b/block/qed-cluster.c
@@ -23,7 +23,8 @@
  * @n:              Maximum number of clusters
  * @offset:         Set to first cluster offset
  *
- * This function scans tables for contiguous allocated or free clusters.
+ * This function scans tables for contiguous clusters.  A contiguous run of
+ * clusters may be allocated, unallocated, or zero.
  */
 static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
                                                   QEDTable *table,
@@ -38,9 +39,14 @@ static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
     *offset = last;
 
     for (i = index + 1; i < end; i++) {
-        if (last == 0) {
-            /* Counting free clusters */
-            if (table->offsets[i] != 0) {
+        if (qed_offset_is_unalloc_cluster(last)) {
+            /* Counting unallocated clusters */
+            if (!qed_offset_is_unalloc_cluster(table->offsets[i])) {
+                break;
+            }
+        } else if (qed_offset_is_zero_cluster(last)) {
+            /* Counting zero clusters */
+            if (!qed_offset_is_zero_cluster(table->offsets[i])) {
                 break;
             }
         } else {
@@ -87,14 +93,19 @@ static void qed_find_cluster_cb(void *opaque, int ret)
     n = qed_count_contiguous_clusters(s, request->l2_table->table,
                                       index, n, &offset);
 
-    ret = offset ? QED_CLUSTER_FOUND : QED_CLUSTER_L2;
-    len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
-              qed_offset_into_cluster(s, find_cluster_cb->pos));
-
-    if (offset && !qed_check_cluster_offset(s, offset)) {
+    if (qed_offset_is_unalloc_cluster(offset)) {
+        ret = QED_CLUSTER_L2;
+    } else if (qed_offset_is_zero_cluster(offset)) {
+        ret = QED_CLUSTER_ZERO;
+    } else if (qed_check_cluster_offset(s, offset)) {
+        ret = QED_CLUSTER_FOUND;
+    } else {
         ret = -EINVAL;
     }
 
+    len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
+              qed_offset_into_cluster(s, find_cluster_cb->pos));
+
 out:
     find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
     qemu_free(find_cluster_cb);
@@ -132,7 +143,7 @@ void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
     len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos);
 
     l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)];
-    if (!l2_offset) {
+    if (qed_offset_is_unalloc_cluster(l2_offset)) {
         cb(opaque, QED_CLUSTER_L1, 0, len);
         return;
     }
diff --git a/block/qed.c b/block/qed.c
index 75ae244..c8c5930 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -573,7 +573,7 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
 {
     QEDIsAllocatedCB *cb = opaque;
     *cb->pnum = len / BDRV_SECTOR_SIZE;
-    cb->is_allocated = ret == QED_CLUSTER_FOUND;
+    cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
 }
 
 static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
@@ -745,7 +745,10 @@ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
  * @table:          L2 table
  * @index:          First cluster index
  * @n:              Number of contiguous clusters
- * @cluster:        First cluster byte offset in image file
+ * @cluster:        First cluster offset
+ *
+ * The cluster offset may be an allocated byte offset in the image file, the
+ * zero cluster marker, or the unallocated cluster marker.
  */
 static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
                                 unsigned int n, uint64_t cluster)
@@ -753,7 +756,10 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
     int i;
     for (i = index; i < index + n; i++) {
         table->offsets[i] = cluster;
-        cluster += s->header.cluster_size;
+        if (!qed_offset_is_unalloc_cluster(cluster) &&
+            !qed_offset_is_zero_cluster(cluster)) {
+            cluster += s->header.cluster_size;
+        }
     }
 }
 
@@ -1075,6 +1081,7 @@ static void qed_aio_write_data(void *opaque, int ret,
 
     case QED_CLUSTER_L2:
     case QED_CLUSTER_L1:
+    case QED_CLUSTER_ZERO:
         qed_aio_write_alloc(acb, len);
         break;
 
@@ -1114,8 +1121,12 @@ static void qed_aio_read_data(void *opaque, int ret,
 
     qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
 
-    /* Handle backing file and unallocated sparse hole reads */
-    if (ret != QED_CLUSTER_FOUND) {
+    /* Handle zero cluster and backing file reads */
+    if (ret == QED_CLUSTER_ZERO) {
+        qemu_iovec_memset(&acb->cur_qiov, 0, acb->cur_qiov.size);
+        qed_aio_next_io(acb, 0);
+        return;
+    } else if (ret != QED_CLUSTER_FOUND) {
         qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
                               qed_aio_next_io, acb);
         return;
diff --git a/block/qed.h b/block/qed.h
index 2925e37..3e1ab84 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -161,6 +161,7 @@ typedef struct {
 
 enum {
     QED_CLUSTER_FOUND,         /* cluster found */
+    QED_CLUSTER_ZERO,          /* zero cluster found */
     QED_CLUSTER_L2,            /* cluster missing in L2 */
     QED_CLUSTER_L1,            /* cluster missing in L1 */
 };
@@ -298,4 +299,29 @@ static inline bool qed_check_table_offset(BDRVQEDState *s, uint64_t offset)
            qed_check_cluster_offset(s, end_offset);
 }
 
+static inline bool qed_offset_is_cluster_aligned(BDRVQEDState *s,
+                                                 uint64_t offset)
+{
+    if (qed_offset_into_cluster(s, offset)) {
+        return false;
+    }
+    return true;
+}
+
+static inline bool qed_offset_is_unalloc_cluster(uint64_t offset)
+{
+    if (offset == 0) {
+        return true;
+    }
+    return false;
+}
+
+static inline bool qed_offset_is_zero_cluster(uint64_t offset)
+{
+    if (offset == 1) {
+        return true;
+    }
+    return false;
+}
+
 #endif /* BLOCK_QED_H */
commit d54f10bba7635b5ad8b750afd2bb2f0f8eb68b45
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Dec 17 15:58:21 2010 +0000

    docs: Describe zero data clusters in QED specification
    
    Zero data clusters are a space-efficient way of storing zeroed regions
    of the image.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/docs/specs/qed_spec.txt b/docs/specs/qed_spec.txt
index 1d5fa87..7982e05 100644
--- a/docs/specs/qed_spec.txt
+++ b/docs/specs/qed_spec.txt
@@ -89,6 +89,7 @@ L1, L2, and data cluster offsets must be aligned to header.cluster_size.  The fo
 
 ===Data cluster offsets===
 * 0 - unallocated.  The data cluster is not yet allocated.
+* 1 - zero.  The data cluster contents are all zeroes and no cluster is allocated.
 
 Future format extensions may wish to store per-offset information.  The least significant 12 bits of an offset are reserved for this purpose and must be set to zero.  Image files with cluster_size > 2^12 will have more unused bits which should also be zeroed.
 
@@ -97,6 +98,13 @@ Reads to an unallocated area of the image file access the backing file.  If ther
 
 Writes to an unallocated area cause a new data clusters to be allocated, and a new L2 table if that is also unallocated.  The new data cluster is populated with data from the backing file (or zeroes if no backing file) and the data being written.
 
+===Zero data clusters===
+Zero data clusters are a space-efficient way of storing zeroed regions of the image.
+
+Reads to a zero data cluster produce zeroes.  Note that the difference between an unallocated and a zero data cluster is that zero data clusters stop the reading of contents from the backing file.
+
+Writes to a zero data cluster cause a new data cluster to be allocated.  The new data cluster is populated with zeroes and the data being written.
+
 ===Logical offset translation===
 Logical offsets are translated into cluster offsets as follows:
 
commit 9df38c47d01eb1fd7eb9d60ac70a4170e638b4a2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 12 13:56:41 2011 +0100

    target-arm: Detect tininess before rounding for FP operations
    
    The ARM architecture mandates that we detect tininess before rounding,
    so set the softfloat fp_status up appropriately.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index ce9a9d8..9172fc7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -269,6 +269,10 @@ void cpu_reset(CPUARMState *env)
     set_flush_to_zero(1, &env->vfp.standard_fp_status);
     set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
     set_default_nan_mode(1, &env->vfp.standard_fp_status);
+    set_float_detect_tininess(float_tininess_before_rounding,
+                              &env->vfp.fp_status);
+    set_float_detect_tininess(float_tininess_before_rounding,
+                              &env->vfp.standard_fp_status);
     tlb_flush(env, 1);
 }
 
commit c29aca44614e12a310dd903dc4fd56b14a6b71c9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 12 13:56:40 2011 +0100

    softfloat: Add setter function for tininess detection mode
    
    Add a setter function for the underflow tininess detection mode,
    in line with the similar functions for other parts of the float status
    structure.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 7abcbe8..c7654d4 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -211,6 +211,10 @@ typedef struct float_status {
 
 void set_float_rounding_mode(int val STATUS_PARAM);
 void set_float_exception_flags(int val STATUS_PARAM);
+INLINE void set_float_detect_tininess(int val STATUS_PARAM)
+{
+    STATUS(float_detect_tininess) = val;
+}
 INLINE void set_flush_to_zero(flag val STATUS_PARAM)
 {
     STATUS(flush_to_zero) = val;
commit 133da6aae1edc0118fbac8cd9ba46dff69ddd5c9
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Mon Apr 11 16:26:23 2011 +0100

    target-arm: Handle UNDEF cases for VDUP (scalar)
    
    Handle the UNDEF cases for VDUP(scalar):
     imm4 == x000
     Q == 1 && Vd<0> == 1
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index be25c8f..6190028 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6057,6 +6057,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 tcg_temp_free_i32(tmp);
             } else if ((insn & 0x380) == 0) {
                 /* VDUP */
+                if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
+                    return 1;
+                }
                 if (insn & (1 << 19)) {
                     tmp = neon_load_reg(rm, 1);
                 } else {
commit 56907d776e1133bf4f633e4e542267d23d2c09cf
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:22 2011 +0100

    target-arm: Treat UNPREDICTABLE VTBL, VTBX case as UNDEF
    
    Catch the UNPREDICTABLE case for Neon VTBL,VTBX, and UNDEF it
    rather than allowing the helper function to index off the end
    of the register file.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index b647c7b..be25c8f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6023,7 +6023,14 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 }
             } else if ((insn & (1 << 10)) == 0) {
                 /* VTBL, VTBX.  */
-                int n = ((insn >> 5) & 0x18) + 8;
+                int n = ((insn >> 8) & 3) + 1;
+                if ((rn + n) > 32) {
+                    /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
+                     * helper function running off the end of the register file.
+                     */
+                    return 1;
+                }
+                n <<= 3;
                 if (insn & (1 << 6)) {
                     tmp = neon_load_reg(rd, 0);
                 } else {
commit fc2a9b37849d25d21d161c1319581420499ab4b2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:21 2011 +0100

    target-arm: Handle UNDEF cases for Neon 2 register misc forms
    
    Add missing UNDEF checks for Neon "two register miscellaneous" forms:
     * all instructions except VMOVN,VQMOVN must UNDEF
       if Q==1 && (Vd<0> == 1 || Vm<0> == 1)
     * VMOVN,VQMOVN,VCVT.F16.F32 UNDEF if Q == 1 || Vm<0> == 1
     * VSHLL,VCVT.F32.F16 UNDEF if Q == 1 || Vd<0> == 1
    (The only other UNDEF case is VZIP,VUZP if Q == 0 && size == 10,
    which we already handle.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4728248..b647c7b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5677,6 +5677,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
                     return 1;
                 }
+                if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
+                    q && ((rm | rd) & 1)) {
+                    return 1;
+                }
                 switch (op) {
                 case NEON_2RM_VREV64:
                     for (pass = 0; pass < (q ? 2 : 1); pass++) {
@@ -5747,6 +5751,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
                     /* also VQMOVUN; op field and mnemonics don't line up */
+                    if (rm & 1) {
+                        return 1;
+                    }
                     TCGV_UNUSED(tmp2);
                     for (pass = 0; pass < 2; pass++) {
                         neon_load_reg64(cpu_V0, rm + pass);
@@ -5762,7 +5769,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                     break;
                 case NEON_2RM_VSHLL:
-                    if (q) {
+                    if (q || (rd & 1)) {
                         return 1;
                     }
                     tmp = neon_load_reg(rm, 0);
@@ -5776,8 +5783,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                     break;
                 case NEON_2RM_VCVT_F16_F32:
-                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
-                      return 1;
+                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
+                        q || (rm & 1)) {
+                        return 1;
+                    }
                     tmp = tcg_temp_new_i32();
                     tmp2 = tcg_temp_new_i32();
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
@@ -5798,8 +5807,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tcg_temp_free_i32(tmp);
                     break;
                 case NEON_2RM_VCVT_F32_F16:
-                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
-                      return 1;
+                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
+                        q || (rd & 1)) {
+                        return 1;
+                    }
                     tmp3 = tcg_temp_new_i32();
                     tmp = neon_load_reg(rm, 0);
                     tmp2 = neon_load_reg(rm, 1);
commit 600b828c448f108b89e1f864f0420a49ccb70d43
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:20 2011 +0100

    target-arm: Simplify checking of size field in Neon 2reg-misc forms
    
    Many of the Neon "2 register misc" instruction forms require invalid
    size fields to cause the instruction to UNDEF. Pull this information
    out into an array; this simplifies the code and also means we can do
    the check early and avoid the problem of leaking TCG temporaries in
    the illegal_op case.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index f47e5ea..4728248 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3662,7 +3662,7 @@ static inline TCGv neon_get_scalar(int size, int reg)
 static int gen_neon_unzip(int rd, int rm, int size, int q)
 {
     TCGv tmp, tmp2;
-    if (size == 3 || (!q && size == 2)) {
+    if (!q && size == 2) {
         return 1;
     }
     tmp = tcg_const_i32(rd);
@@ -3701,7 +3701,7 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
 static int gen_neon_zip(int rd, int rm, int size, int q)
 {
     TCGv tmp, tmp2;
-    if (size == 3 || (!q && size == 2)) {
+    if (!q && size == 2) {
         return 1;
     }
     tmp = tcg_const_i32(rd);
@@ -4312,6 +4312,113 @@ static const uint8_t neon_3r_sizes[] = {
     [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
 };
 
+/* Symbolic constants for op fields for Neon 2-register miscellaneous.
+ * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
+ * table A7-13.
+ */
+#define NEON_2RM_VREV64 0
+#define NEON_2RM_VREV32 1
+#define NEON_2RM_VREV16 2
+#define NEON_2RM_VPADDL 4
+#define NEON_2RM_VPADDL_U 5
+#define NEON_2RM_VCLS 8
+#define NEON_2RM_VCLZ 9
+#define NEON_2RM_VCNT 10
+#define NEON_2RM_VMVN 11
+#define NEON_2RM_VPADAL 12
+#define NEON_2RM_VPADAL_U 13
+#define NEON_2RM_VQABS 14
+#define NEON_2RM_VQNEG 15
+#define NEON_2RM_VCGT0 16
+#define NEON_2RM_VCGE0 17
+#define NEON_2RM_VCEQ0 18
+#define NEON_2RM_VCLE0 19
+#define NEON_2RM_VCLT0 20
+#define NEON_2RM_VABS 22
+#define NEON_2RM_VNEG 23
+#define NEON_2RM_VCGT0_F 24
+#define NEON_2RM_VCGE0_F 25
+#define NEON_2RM_VCEQ0_F 26
+#define NEON_2RM_VCLE0_F 27
+#define NEON_2RM_VCLT0_F 28
+#define NEON_2RM_VABS_F 30
+#define NEON_2RM_VNEG_F 31
+#define NEON_2RM_VSWP 32
+#define NEON_2RM_VTRN 33
+#define NEON_2RM_VUZP 34
+#define NEON_2RM_VZIP 35
+#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
+#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
+#define NEON_2RM_VSHLL 38
+#define NEON_2RM_VCVT_F16_F32 44
+#define NEON_2RM_VCVT_F32_F16 46
+#define NEON_2RM_VRECPE 56
+#define NEON_2RM_VRSQRTE 57
+#define NEON_2RM_VRECPE_F 58
+#define NEON_2RM_VRSQRTE_F 59
+#define NEON_2RM_VCVT_FS 60
+#define NEON_2RM_VCVT_FU 61
+#define NEON_2RM_VCVT_SF 62
+#define NEON_2RM_VCVT_UF 63
+
+static int neon_2rm_is_float_op(int op)
+{
+    /* Return true if this neon 2reg-misc op is float-to-float */
+    return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
+            op >= NEON_2RM_VRECPE_F);
+}
+
+/* Each entry in this array has bit n set if the insn allows
+ * size value n (otherwise it will UNDEF). Since unallocated
+ * op values will have no bits set they always UNDEF.
+ */
+static const uint8_t neon_2rm_sizes[] = {
+    [NEON_2RM_VREV64] = 0x7,
+    [NEON_2RM_VREV32] = 0x3,
+    [NEON_2RM_VREV16] = 0x1,
+    [NEON_2RM_VPADDL] = 0x7,
+    [NEON_2RM_VPADDL_U] = 0x7,
+    [NEON_2RM_VCLS] = 0x7,
+    [NEON_2RM_VCLZ] = 0x7,
+    [NEON_2RM_VCNT] = 0x1,
+    [NEON_2RM_VMVN] = 0x1,
+    [NEON_2RM_VPADAL] = 0x7,
+    [NEON_2RM_VPADAL_U] = 0x7,
+    [NEON_2RM_VQABS] = 0x7,
+    [NEON_2RM_VQNEG] = 0x7,
+    [NEON_2RM_VCGT0] = 0x7,
+    [NEON_2RM_VCGE0] = 0x7,
+    [NEON_2RM_VCEQ0] = 0x7,
+    [NEON_2RM_VCLE0] = 0x7,
+    [NEON_2RM_VCLT0] = 0x7,
+    [NEON_2RM_VABS] = 0x7,
+    [NEON_2RM_VNEG] = 0x7,
+    [NEON_2RM_VCGT0_F] = 0x4,
+    [NEON_2RM_VCGE0_F] = 0x4,
+    [NEON_2RM_VCEQ0_F] = 0x4,
+    [NEON_2RM_VCLE0_F] = 0x4,
+    [NEON_2RM_VCLT0_F] = 0x4,
+    [NEON_2RM_VABS_F] = 0x4,
+    [NEON_2RM_VNEG_F] = 0x4,
+    [NEON_2RM_VSWP] = 0x1,
+    [NEON_2RM_VTRN] = 0x7,
+    [NEON_2RM_VUZP] = 0x7,
+    [NEON_2RM_VZIP] = 0x7,
+    [NEON_2RM_VMOVN] = 0x7,
+    [NEON_2RM_VQMOVN] = 0x7,
+    [NEON_2RM_VSHLL] = 0x7,
+    [NEON_2RM_VCVT_F16_F32] = 0x2,
+    [NEON_2RM_VCVT_F32_F16] = 0x2,
+    [NEON_2RM_VRECPE] = 0x4,
+    [NEON_2RM_VRSQRTE] = 0x4,
+    [NEON_2RM_VRECPE_F] = 0x4,
+    [NEON_2RM_VRSQRTE_F] = 0x4,
+    [NEON_2RM_VCVT_FS] = 0x4,
+    [NEON_2RM_VCVT_FU] = 0x4,
+    [NEON_2RM_VCVT_SF] = 0x4,
+    [NEON_2RM_VCVT_UF] = 0x4,
+};
+
 /* Translate a NEON data processing instruction.  Return nonzero if the
    instruction is invalid.
    We process data in a mixture of 32-bit and 64-bit chunks.
@@ -5566,10 +5673,12 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 /* Two register misc.  */
                 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
                 size = (insn >> 18) & 3;
+                /* UNDEF for unknown op values and bad op-size combinations */
+                if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
+                    return 1;
+                }
                 switch (op) {
-                case 0: /* VREV64 */
-                    if (size == 3)
-                        return 1;
+                case NEON_2RM_VREV64:
                     for (pass = 0; pass < (q ? 2 : 1); pass++) {
                         tmp = neon_load_reg(rm, pass * 2);
                         tmp2 = neon_load_reg(rm, pass * 2 + 1);
@@ -5592,10 +5701,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         }
                     }
                     break;
-                case 4: case 5: /* VPADDL */
-                case 12: case 13: /* VPADAL */
-                    if (size == 3)
-                        return 1;
+                case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
+                case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
                     for (pass = 0; pass < q + 1; pass++) {
                         tmp = neon_load_reg(rm, pass * 2);
                         gen_neon_widen(cpu_V0, tmp, size, op & 1);
@@ -5607,7 +5714,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         case 2: tcg_gen_add_i64(CPU_V001); break;
                         default: abort();
                         }
-                        if (op >= 12) {
+                        if (op >= NEON_2RM_VPADAL) {
                             /* Accumulate.  */
                             neon_load_reg64(cpu_V1, rd + pass);
                             gen_neon_addl(size);
@@ -5615,7 +5722,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg64(cpu_V0, rd + pass);
                     }
                     break;
-                case 33: /* VTRN */
+                case NEON_2RM_VTRN:
                     if (size == 2) {
                         int n;
                         for (n = 0; n < (q ? 4 : 2); n += 2) {
@@ -5628,24 +5735,24 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         goto elementwise;
                     }
                     break;
-                case 34: /* VUZP */
+                case NEON_2RM_VUZP:
                     if (gen_neon_unzip(rd, rm, size, q)) {
                         return 1;
                     }
                     break;
-                case 35: /* VZIP */
+                case NEON_2RM_VZIP:
                     if (gen_neon_zip(rd, rm, size, q)) {
                         return 1;
                     }
                     break;
-                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
-                    if (size == 3)
-                        return 1;
+                case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
+                    /* also VQMOVUN; op field and mnemonics don't line up */
                     TCGV_UNUSED(tmp2);
                     for (pass = 0; pass < 2; pass++) {
                         neon_load_reg64(cpu_V0, rm + pass);
                         tmp = tcg_temp_new_i32();
-                        gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
+                        gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
+                                           tmp, cpu_V0);
                         if (pass == 0) {
                             tmp2 = tmp;
                         } else {
@@ -5654,9 +5761,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         }
                     }
                     break;
-                case 38: /* VSHLL */
-                    if (q || size == 3)
+                case NEON_2RM_VSHLL:
+                    if (q) {
                         return 1;
+                    }
                     tmp = neon_load_reg(rm, 0);
                     tmp2 = neon_load_reg(rm, 1);
                     for (pass = 0; pass < 2; pass++) {
@@ -5667,7 +5775,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg64(cpu_V0, rd + pass);
                     }
                     break;
-                case 44: /* VCVT.F16.F32 */
+                case NEON_2RM_VCVT_F16_F32:
                     if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                       return 1;
                     tmp = tcg_temp_new_i32();
@@ -5689,7 +5797,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     neon_store_reg(rd, 1, tmp2);
                     tcg_temp_free_i32(tmp);
                     break;
-                case 46: /* VCVT.F32.F16 */
+                case NEON_2RM_VCVT_F32_F16:
                     if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                       return 1;
                     tmp3 = tcg_temp_new_i32();
@@ -5714,7 +5822,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 default:
                 elementwise:
                     for (pass = 0; pass < (q ? 4 : 2); pass++) {
-                        if (op == 30 || op == 31 || op >= 58) {
+                        if (neon_2rm_is_float_op(op)) {
                             tcg_gen_ld_f32(cpu_F0s, cpu_env,
                                            neon_reg_offset(rm, pass));
                             TCGV_UNUSED(tmp);
@@ -5722,183 +5830,178 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tmp = neon_load_reg(rm, pass);
                         }
                         switch (op) {
-                        case 1: /* VREV32 */
+                        case NEON_2RM_VREV32:
                             switch (size) {
                             case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
                             case 1: gen_swap_half(tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 2: /* VREV16 */
-                            if (size != 0)
-                                return 1;
+                        case NEON_2RM_VREV16:
                             gen_rev16(tmp);
                             break;
-                        case 8: /* CLS */
+                        case NEON_2RM_VCLS:
                             switch (size) {
                             case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
                             case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
                             case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 9: /* CLZ */
+                        case NEON_2RM_VCLZ:
                             switch (size) {
                             case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
                             case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
                             case 2: gen_helper_clz(tmp, tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 10: /* CNT */
-                            if (size != 0)
-                                return 1;
+                        case NEON_2RM_VCNT:
                             gen_helper_neon_cnt_u8(tmp, tmp);
                             break;
-                        case 11: /* VNOT */
-                            if (size != 0)
-                                return 1;
+                        case NEON_2RM_VMVN:
                             tcg_gen_not_i32(tmp, tmp);
                             break;
-                        case 14: /* VQABS */
+                        case NEON_2RM_VQABS:
                             switch (size) {
                             case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
                             case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
                             case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 15: /* VQNEG */
+                        case NEON_2RM_VQNEG:
                             switch (size) {
                             case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
                             case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
                             case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 16: case 19: /* VCGT #0, VCLE #0 */
+                        case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
                             tmp2 = tcg_const_i32(0);
                             switch(size) {
                             case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
                             case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
                             case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
-                            default: return 1;
+                            default: abort();
                             }
                             tcg_temp_free(tmp2);
-                            if (op == 19)
+                            if (op == NEON_2RM_VCLE0) {
                                 tcg_gen_not_i32(tmp, tmp);
+                            }
                             break;
-                        case 17: case 20: /* VCGE #0, VCLT #0 */
+                        case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
                             tmp2 = tcg_const_i32(0);
                             switch(size) {
                             case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
                             case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
                             case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
-                            default: return 1;
+                            default: abort();
                             }
                             tcg_temp_free(tmp2);
-                            if (op == 20)
+                            if (op == NEON_2RM_VCLT0) {
                                 tcg_gen_not_i32(tmp, tmp);
+                            }
                             break;
-                        case 18: /* VCEQ #0 */
+                        case NEON_2RM_VCEQ0:
                             tmp2 = tcg_const_i32(0);
                             switch(size) {
                             case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
                             case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
                             case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
-                            default: return 1;
+                            default: abort();
                             }
                             tcg_temp_free(tmp2);
                             break;
-                        case 22: /* VABS */
+                        case NEON_2RM_VABS:
                             switch(size) {
                             case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
                             case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
                             case 2: tcg_gen_abs_i32(tmp, tmp); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
-                        case 23: /* VNEG */
-                            if (size == 3)
-                                return 1;
+                        case NEON_2RM_VNEG:
                             tmp2 = tcg_const_i32(0);
                             gen_neon_rsb(size, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
-                        case 24: /* Float VCGT #0 */
+                        case NEON_2RM_VCGT0_F:
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
-                        case 25: /* Float VCGE #0 */
+                        case NEON_2RM_VCGE0_F:
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cge_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
-                        case 26: /* Float VCEQ #0 */
+                        case NEON_2RM_VCEQ0_F:
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
-                        case 27: /* Float VCLE #0 */
+                        case NEON_2RM_VCLE0_F:
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cge_f32(tmp, tmp2, tmp);
                             tcg_temp_free(tmp2);
                             break;
-                        case 28: /* Float VCLT #0 */
+                        case NEON_2RM_VCLT0_F:
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
                             tcg_temp_free(tmp2);
                             break;
-                        case 30: /* Float VABS */
+                        case NEON_2RM_VABS_F:
                             gen_vfp_abs(0);
                             break;
-                        case 31: /* Float VNEG */
+                        case NEON_2RM_VNEG_F:
                             gen_vfp_neg(0);
                             break;
-                        case 32: /* VSWP */
+                        case NEON_2RM_VSWP:
                             tmp2 = neon_load_reg(rd, pass);
                             neon_store_reg(rm, pass, tmp2);
                             break;
-                        case 33: /* VTRN */
+                        case NEON_2RM_VTRN:
                             tmp2 = neon_load_reg(rd, pass);
                             switch (size) {
                             case 0: gen_neon_trn_u8(tmp, tmp2); break;
                             case 1: gen_neon_trn_u16(tmp, tmp2); break;
-                            case 2: abort();
-                            default: return 1;
+                            default: abort();
                             }
                             neon_store_reg(rm, pass, tmp2);
                             break;
-                        case 56: /* Integer VRECPE */
+                        case NEON_2RM_VRECPE:
                             gen_helper_recpe_u32(tmp, tmp, cpu_env);
                             break;
-                        case 57: /* Integer VRSQRTE */
+                        case NEON_2RM_VRSQRTE:
                             gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
                             break;
-                        case 58: /* Float VRECPE */
+                        case NEON_2RM_VRECPE_F:
                             gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
                             break;
-                        case 59: /* Float VRSQRTE */
+                        case NEON_2RM_VRSQRTE_F:
                             gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
                             break;
-                        case 60: /* VCVT.F32.S32 */
+                        case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
                             gen_vfp_sito(0);
                             break;
-                        case 61: /* VCVT.F32.U32 */
+                        case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
                             gen_vfp_uito(0);
                             break;
-                        case 62: /* VCVT.S32.F32 */
+                        case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
                             gen_vfp_tosiz(0);
                             break;
-                        case 63: /* VCVT.U32.F32 */
+                        case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
                             gen_vfp_touiz(0);
                             break;
                         default:
-                            /* Reserved: 21, 29, 39-56 */
-                            return 1;
+                            /* Reserved op values were caught by the
+                             * neon_2rm_sizes[] check earlier.
+                             */
+                            abort();
                         }
-                        if (op == 30 || op == 31 || op >= 58) {
+                        if (neon_2rm_is_float_op(op)) {
                             tcg_gen_st_f32(cpu_F0s, cpu_env,
                                            neon_reg_offset(rd, pass));
                         } else {
commit 52579ea1c201ce10a5fe6f5734373543e462e345
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:19 2011 +0100

    target-arm: Handle UNDEF cases for VEXT
    
    VEXT must UNDEF if Q == 1 && (Vd<0> == 1 || Vr<0> == 1 || Vm<0> == 1)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 15c2015..f47e5ea 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5514,6 +5514,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 if (imm > 7 && !q)
                     return 1;
 
+                if (q && ((rd | rn | rm) & 1)) {
+                    return 1;
+                }
+
                 if (imm == 0) {
                     neon_load_reg64(cpu_V0, rn);
                     if (q) {
commit 3e3326dfb003df0f2f9209c78c25b965aa6022f1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:18 2011 +0100

    target-arm: Handle UNDEF cases for Neon 2 regs + scalar forms
    
    Add missing checks for cases which must UNDEF in the Neon "2 registers and
    a scalar" data processing instruction space.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9ff5af0..15c2015 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5368,16 +5368,29 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                 }
             } else {
-                /* Two registers and a scalar.  */
+                /* Two registers and a scalar. NB that for ops of this form
+                 * the ARM ARM labels bit 24 as Q, but it is in our variable
+                 * 'u', not 'q'.
+                 */
+                if (size == 0) {
+                    return 1;
+                }
                 switch (op) {
-                case 0: /* Integer VMLA scalar */
                 case 1: /* Float VMLA scalar */
-                case 4: /* Integer VMLS scalar */
                 case 5: /* Floating point VMLS scalar */
-                case 8: /* Integer VMUL scalar */
                 case 9: /* Floating point VMUL scalar */
+                    if (size == 1) {
+                        return 1;
+                    }
+                    /* fall through */
+                case 0: /* Integer VMLA scalar */
+                case 4: /* Integer VMLS scalar */
+                case 8: /* Integer VMUL scalar */
                 case 12: /* VQDMULH scalar */
                 case 13: /* VQRDMULH scalar */
+                    if (u && ((rd | rn) & 1)) {
+                        return 1;
+                    }
                     tmp = neon_get_scalar(size, rm);
                     neon_store_scratch(0, tmp);
                     for (pass = 0; pass < (u ? 4 : 2); pass++) {
@@ -5402,7 +5415,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
                             case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
                             case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
-                            default: return 1;
+                            default: abort();
                             }
                         }
                         tcg_temp_free_i32(tmp2);
@@ -5430,15 +5443,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg(rd, pass, tmp);
                     }
                     break;
-                case 2: /* VMLAL sclar */
                 case 3: /* VQDMLAL scalar */
-                case 6: /* VMLSL scalar */
                 case 7: /* VQDMLSL scalar */
-                case 10: /* VMULL scalar */
                 case 11: /* VQDMULL scalar */
-                    if (size == 0 && (op == 3 || op == 7 || op == 11))
+                    if (u == 1) {
                         return 1;
-
+                    }
+                    /* fall through */
+                case 2: /* VMLAL sclar */
+                case 6: /* VMLSL scalar */
+                case 10: /* VMULL scalar */
+                    if (rd & 1) {
+                        return 1;
+                    }
                     tmp2 = neon_get_scalar(size, rm);
                     /* We need a copy of tmp2 because gen_neon_mull
                      * deletes it during pass 0.  */
commit 695272dcb976897639c034b8fe3d32699ada6482
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:17 2011 +0100

    target-arm: Handle UNDEF cases for Neon 3-regs-different-widths
    
    Add missing UNDEF checks for instructions in the Neon "3 registers of
    different widths" data processing space.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0a9b3cf..9ff5af0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5174,31 +5174,47 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 int src1_wide;
                 int src2_wide;
                 int prewiden;
-                /* prewiden, src1_wide, src2_wide */
-                static const int neon_3reg_wide[16][3] = {
-                    {1, 0, 0}, /* VADDL */
-                    {1, 1, 0}, /* VADDW */
-                    {1, 0, 0}, /* VSUBL */
-                    {1, 1, 0}, /* VSUBW */
-                    {0, 1, 1}, /* VADDHN */
-                    {0, 0, 0}, /* VABAL */
-                    {0, 1, 1}, /* VSUBHN */
-                    {0, 0, 0}, /* VABDL */
-                    {0, 0, 0}, /* VMLAL */
-                    {0, 0, 0}, /* VQDMLAL */
-                    {0, 0, 0}, /* VMLSL */
-                    {0, 0, 0}, /* VQDMLSL */
-                    {0, 0, 0}, /* Integer VMULL */
-                    {0, 0, 0}, /* VQDMULL */
-                    {0, 0, 0}  /* Polynomial VMULL */
+                /* undefreq: bit 0 : UNDEF if size != 0
+                 *           bit 1 : UNDEF if size == 0
+                 *           bit 2 : UNDEF if U == 1
+                 * Note that [1:0] set implies 'always UNDEF'
+                 */
+                int undefreq;
+                /* prewiden, src1_wide, src2_wide, undefreq */
+                static const int neon_3reg_wide[16][4] = {
+                    {1, 0, 0, 0}, /* VADDL */
+                    {1, 1, 0, 0}, /* VADDW */
+                    {1, 0, 0, 0}, /* VSUBL */
+                    {1, 1, 0, 0}, /* VSUBW */
+                    {0, 1, 1, 0}, /* VADDHN */
+                    {0, 0, 0, 0}, /* VABAL */
+                    {0, 1, 1, 0}, /* VSUBHN */
+                    {0, 0, 0, 0}, /* VABDL */
+                    {0, 0, 0, 0}, /* VMLAL */
+                    {0, 0, 0, 6}, /* VQDMLAL */
+                    {0, 0, 0, 0}, /* VMLSL */
+                    {0, 0, 0, 6}, /* VQDMLSL */
+                    {0, 0, 0, 0}, /* Integer VMULL */
+                    {0, 0, 0, 2}, /* VQDMULL */
+                    {0, 0, 0, 5}, /* Polynomial VMULL */
+                    {0, 0, 0, 3}, /* Reserved: always UNDEF */
                 };
 
                 prewiden = neon_3reg_wide[op][0];
                 src1_wide = neon_3reg_wide[op][1];
                 src2_wide = neon_3reg_wide[op][2];
+                undefreq = neon_3reg_wide[op][3];
 
-                if (size == 0 && (op == 9 || op == 11 || op == 13))
+                if (((undefreq & 1) && (size != 0)) ||
+                    ((undefreq & 2) && (size == 0)) ||
+                    ((undefreq & 4) && u)) {
+                    return 1;
+                }
+                if ((src1_wide && (rn & 1)) ||
+                    (src2_wide && (rm & 1)) ||
+                    (!src2_wide && (rd & 1))) {
                     return 1;
+                }
 
                 /* Avoid overlapping operands.  Wide source operands are
                    always aligned so will never overlap with wide
@@ -5279,8 +5295,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tcg_temp_free_i32(tmp2);
                         tcg_temp_free_i32(tmp);
                         break;
-                    default: /* 15 is RESERVED.  */
-                        return 1;
+                    default: /* 15 is RESERVED: caught earlier  */
+                        abort();
                     }
                     if (op == 13) {
                         /* VQDMULL */
commit 7d80fee5b9e663148ddee714e3b755a0af20508d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:16 2011 +0100

    target-arm: Handle UNDEF cases for Neon invalid modified-immediates
    
    For Neon "one register and a modified immediate value" forms, the
    combination op=1 cmode=1111 is unallocated and should UNDEF.
    All instructions of this form also UNDEF if Q == 1 and Vd<0> == 1.
    We also add a comment on the only UNPREDICTABLE in this space.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index a86c54c..0a9b3cf 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5084,11 +5084,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
         } else { /* (insn & 0x00380080) == 0 */
             int invert;
+            if (q && (rd & 1)) {
+                return 1;
+            }
 
             op = (insn >> 8) & 0xf;
             /* One register and immediate.  */
             imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
             invert = (insn & (1 << 5)) != 0;
+            /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
+             * We choose to not special-case this and will behave as if a
+             * valid constant encoding of 0 had been given.
+             */
             switch (op) {
             case 0: case 1:
                 /* no-op */
@@ -5120,6 +5127,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     imm = ~imm;
                 break;
             case 15:
+                if (invert) {
+                    return 1;
+                }
                 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
                       | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
                 break;
commit 2bc70834e867e7a0c4f30d374405acf8d81bba03
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:15 2011 +0100

    target-arm: Collapse VSRI case into VSHL, VSLI
    
    Collapse some switch cases for VSRI into those for VSHL, VSLI,
    since the bodies are the same. (This is not completely obvious
    for the size < 3 case, but since for VSRI we know U=1 the
    GEN_NEON_INTEGER_OP() expansion is equivalent to the open-coded
    VSHL/VSLI case.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index c0ffa9f..a86c54c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4813,8 +4813,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 4: /* VSRI */
-                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
-                            break;
                         case 5: /* VSHL, VSLI */
                             gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
                             break;
@@ -4867,8 +4865,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             GEN_NEON_INTEGER_OP(rshl);
                             break;
                         case 4: /* VSRI */
-                            GEN_NEON_INTEGER_OP(shl);
-                            break;
                         case 5: /* VSHL, VSLI */
                             switch (size) {
                             case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
commit cc13115bdecb4596fd4201f16455220a7d1a85f8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:14 2011 +0100

    target-arm: Handle UNDEF cases for Neon "2 regs and shift" insns
    
    Correctly handle all the UNDEF cases for Neon instructions of the
    "2 registers and shift" form, and make sure that we check for these
    cases early enough not to leak TCG temporaries.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0cf933d..c0ffa9f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4744,7 +4744,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             /* Two registers and shift.  */
             op = (insn >> 8) & 0xf;
             if (insn & (1 << 7)) {
-                /* 64-bit shift.   */
+                /* 64-bit shift. */
+                if (op > 7) {
+                    return 1;
+                }
                 size = 3;
             } else {
                 size = 2;
@@ -4757,6 +4760,12 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             if (op < 8) {
                 /* Shift by immediate:
                    VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
+                if (q && ((rd | rm) & 1)) {
+                    return 1;
+                }
+                if (!u && (op == 4 || op == 6)) {
+                    return 1;
+                }
                 /* Right shifts are encoded as N - shift, where N is the
                    element size in bits.  */
                 if (op <= 4)
@@ -4804,20 +4813,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 4: /* VSRI */
-                            if (!u)
-                                return 1;
                             gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 5: /* VSHL, VSLI */
                             gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 6: /* VQSHLU */
-                            if (u) {
-                                gen_helper_neon_qshlu_s64(cpu_V0,
-                                                          cpu_V0, cpu_V1);
-                            } else {
-                                return 1;
-                            }
+                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
                             break;
                         case 7: /* VQSHL */
                             if (u) {
@@ -4865,8 +4867,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             GEN_NEON_INTEGER_OP(rshl);
                             break;
                         case 4: /* VSRI */
-                            if (!u)
-                                return 1;
                             GEN_NEON_INTEGER_OP(shl);
                             break;
                         case 5: /* VSHL, VSLI */
@@ -4874,13 +4874,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
                             case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
                             case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
-                            default: return 1;
+                            default: abort();
                             }
                             break;
                         case 6: /* VQSHLU */
-                            if (!u) {
-                                return 1;
-                            }
                             switch (size) {
                             case 0:
                                 gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
@@ -4892,7 +4889,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
                                 break;
                             default:
-                                return 1;
+                                abort();
                             }
                             break;
                         case 7: /* VQSHL */
@@ -4950,7 +4947,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 /* Shift by immediate and narrow:
                    VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
                 int input_unsigned = (op == 8) ? !u : u;
-
+                if (rm & 1) {
+                    return 1;
+                }
                 shift = shift - (1 << (size + 3));
                 size++;
                 if (size == 3) {
@@ -5018,9 +5017,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tcg_temp_free_i32(tmp2);
                 }
             } else if (op == 10) {
-                /* VSHLL */
-                if (q || size == 3)
+                /* VSHLL, VMOVL */
+                if (q || (rd & 1)) {
                     return 1;
+                }
                 tmp = neon_load_reg(rm, 0);
                 tmp2 = neon_load_reg(rm, 1);
                 for (pass = 0; pass < 2; pass++) {
@@ -5061,6 +5061,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 }
             } else if (op >= 14) {
                 /* VCVT fixed-point.  */
+                if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
+                    return 1;
+                }
                 /* We have already masked out the must-be-1 top bit of imm6,
                  * hence this 32-shift where the ARM ARM has 64-imm6.
                  */
commit a5a14945da2c9ea8903c69af22274c33ad9488f7
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Mon Apr 11 16:26:13 2011 +0100

    target-arm: Simplify three-register pairwise code
    
    Since we know that the case of (pairwise && q) has been caught
    earlier, we can simplify the register setup code for each pass
    in the three-register-same-size Neon loop.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5ffbace..0cf933d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4328,7 +4328,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
     int count;
     int pairwise;
     int u;
-    int n;
     uint32_t imm, mask;
     TCGv tmp, tmp2, tmp3, tmp4, tmp5;
     TCGv_i64 tmp64;
@@ -4480,16 +4479,12 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
 
         if (pairwise) {
             /* Pairwise.  */
-            if (q)
-                n = (pass & 1) * 2;
-            else
-                n = 0;
-            if (pass < q + 1) {
-                tmp = neon_load_reg(rn, n);
-                tmp2 = neon_load_reg(rn, n + 1);
+            if (pass < 1) {
+                tmp = neon_load_reg(rn, 0);
+                tmp2 = neon_load_reg(rn, 1);
             } else {
-                tmp = neon_load_reg(rm, n);
-                tmp2 = neon_load_reg(rm, n + 1);
+                tmp = neon_load_reg(rm, 0);
+                tmp2 = neon_load_reg(rm, 1);
             }
         } else {
             /* Elementwise.  */
@@ -5147,6 +5142,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     /* VMOV, VMVN.  */
                     tmp = tcg_temp_new_i32();
                     if (op == 14 && invert) {
+                        int n;
                         uint32_t val;
                         val = 0;
                         for (n = 0; n < 4; n++) {
@@ -5575,6 +5571,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case 33: /* VTRN */
                     if (size == 2) {
+                        int n;
                         for (n = 0; n < (q ? 4 : 2); n += 2) {
                             tmp = neon_load_reg(rm, n);
                             tmp2 = neon_load_reg(rd, n + 1);
@@ -5866,7 +5863,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 }
             } else if ((insn & (1 << 10)) == 0) {
                 /* VTBL, VTBX.  */
-                n = ((insn >> 5) & 0x18) + 8;
+                int n = ((insn >> 5) & 0x18) + 8;
                 if (insn & (1 << 6)) {
                     tmp = neon_load_reg(rd, 0);
                 } else {
commit 25f84f79481db5363c638dd95d5c2a0a0e430cee
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:12 2011 +0100

    target-arm: Handle UNDEF cases for Neon 3-regs-same insns
    
    Correct the handling of UNDEF cases for the NEON "3 registers same
    size" forms, by adding missing checks and rationalising some others
    so they are done early enough to avoid leaking TCG temporaries.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 3fa27e1..5ffbace 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4348,6 +4348,12 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
         if ((neon_3r_sizes[op] & (1 << size)) == 0) {
             return 1;
         }
+        /* All insns of this form UNDEF for either this condition or the
+         * superset of cases "Q==1"; we catch the latter later.
+         */
+        if (q && ((rd | rn | rm) & 1)) {
+            return 1;
+        }
         if (size == 3 && op != NEON_3R_LOGIC) {
             /* 64-bit element instructions. */
             for (pass = 0; pass < (q ? 2 : 1); pass++) {
@@ -4410,6 +4416,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
             return 0;
         }
+        pairwise = 0;
         switch (op) {
         case NEON_3R_VSHL:
         case NEON_3R_VQSHL:
@@ -4421,25 +4428,54 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 rtmp = rn;
                 rn = rm;
                 rm = rtmp;
-                pairwise = 0;
             }
             break;
+        case NEON_3R_VPADD:
+            if (u) {
+                return 1;
+            }
+            /* Fall through */
         case NEON_3R_VPMAX:
         case NEON_3R_VPMIN:
-        case NEON_3R_VPADD:
             pairwise = 1;
             break;
-        case NEON_3R_FLOAT_ARITH: /* VADD, VSUB, VPADD, VABD (float) */
-            pairwise = (u && size < 2);
+        case NEON_3R_FLOAT_ARITH:
+            pairwise = (u && size < 2); /* if VPADD (float) */
+            break;
+        case NEON_3R_FLOAT_MINMAX:
+            pairwise = u; /* if VPMIN/VPMAX (float) */
+            break;
+        case NEON_3R_FLOAT_CMP:
+            if (!u && size) {
+                /* no encoding for U=0 C=1x */
+                return 1;
+            }
+            break;
+        case NEON_3R_FLOAT_ACMP:
+            if (!u) {
+                return 1;
+            }
+            break;
+        case NEON_3R_VRECPS_VRSQRTS:
+            if (u) {
+                return 1;
+            }
             break;
-        case NEON_3R_FLOAT_MINMAX: /* VPMIN/VPMAX (float) */
-            pairwise = u;
+        case NEON_3R_VMUL:
+            if (u && (size != 0)) {
+                /* UNDEF on invalid size for polynomial subcase */
+                return 1;
+            }
             break;
         default:
-            pairwise = 0;
             break;
         }
 
+        if (pairwise && q) {
+            /* All the pairwise insns UNDEF if Q is set */
+            return 1;
+        }
+
         for (pass = 0; pass < (q ? 4 : 2); pass++) {
 
         if (pairwise) {
@@ -4621,8 +4657,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
             break;
         case NEON_3R_VPADD:
-            if (u)
-                return 1;
             switch (size) {
             case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
             case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
@@ -4671,8 +4705,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
             break;
         case NEON_3R_FLOAT_ACMP:
-            if (!u)
-                return 1;
             if (size == 0)
                 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
             else
commit 62698be3bac2e4c969205f3849c48922e0e76e88
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 11 16:26:11 2011 +0100

    target-arm: Use lookup table for size check on Neon 3-reg-same insns
    
    Simplify the checks for invalid size values for the Neon "three registers
    of the same size" instruction forms (and add them where they were missing)
    by using a lookup table.
    
    This includes adding symbolic constants for the op values in this space,
    since we now use them in multiple places.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 998cfd5..3fa27e1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3558,15 +3558,14 @@ static void gen_nop_hint(DisasContext *s, int val)
 
 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
 
-static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
+static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
 {
     switch (size) {
     case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
     case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
     case 2: tcg_gen_add_i32(t0, t0, t1); break;
-    default: return 1;
+    default: abort();
     }
-    return 0;
 }
 
 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
@@ -4245,6 +4244,74 @@ static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
     }
 }
 
+/* Symbolic constants for op fields for Neon 3-register same-length.
+ * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
+ * table A7-9.
+ */
+#define NEON_3R_VHADD 0
+#define NEON_3R_VQADD 1
+#define NEON_3R_VRHADD 2
+#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
+#define NEON_3R_VHSUB 4
+#define NEON_3R_VQSUB 5
+#define NEON_3R_VCGT 6
+#define NEON_3R_VCGE 7
+#define NEON_3R_VSHL 8
+#define NEON_3R_VQSHL 9
+#define NEON_3R_VRSHL 10
+#define NEON_3R_VQRSHL 11
+#define NEON_3R_VMAX 12
+#define NEON_3R_VMIN 13
+#define NEON_3R_VABD 14
+#define NEON_3R_VABA 15
+#define NEON_3R_VADD_VSUB 16
+#define NEON_3R_VTST_VCEQ 17
+#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
+#define NEON_3R_VMUL 19
+#define NEON_3R_VPMAX 20
+#define NEON_3R_VPMIN 21
+#define NEON_3R_VQDMULH_VQRDMULH 22
+#define NEON_3R_VPADD 23
+#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
+#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
+#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
+#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
+#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
+#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
+
+static const uint8_t neon_3r_sizes[] = {
+    [NEON_3R_VHADD] = 0x7,
+    [NEON_3R_VQADD] = 0xf,
+    [NEON_3R_VRHADD] = 0x7,
+    [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
+    [NEON_3R_VHSUB] = 0x7,
+    [NEON_3R_VQSUB] = 0xf,
+    [NEON_3R_VCGT] = 0x7,
+    [NEON_3R_VCGE] = 0x7,
+    [NEON_3R_VSHL] = 0xf,
+    [NEON_3R_VQSHL] = 0xf,
+    [NEON_3R_VRSHL] = 0xf,
+    [NEON_3R_VQRSHL] = 0xf,
+    [NEON_3R_VMAX] = 0x7,
+    [NEON_3R_VMIN] = 0x7,
+    [NEON_3R_VABD] = 0x7,
+    [NEON_3R_VABA] = 0x7,
+    [NEON_3R_VADD_VSUB] = 0xf,
+    [NEON_3R_VTST_VCEQ] = 0x7,
+    [NEON_3R_VML] = 0x7,
+    [NEON_3R_VMUL] = 0x7,
+    [NEON_3R_VPMAX] = 0x7,
+    [NEON_3R_VPMIN] = 0x7,
+    [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
+    [NEON_3R_VPADD] = 0x7,
+    [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
+    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
+};
+
 /* Translate a NEON data processing instruction.  Return nonzero if the
    instruction is invalid.
    We process data in a mixture of 32-bit and 64-bit chunks.
@@ -4277,56 +4344,59 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
     if ((insn & (1 << 23)) == 0) {
         /* Three register same length.  */
         op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
-        if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
-                          || op == 10 || op  == 11 || op == 16)) {
-            /* 64-bit element instructions.  */
+        /* Catch invalid op and bad size combinations: UNDEF */
+        if ((neon_3r_sizes[op] & (1 << size)) == 0) {
+            return 1;
+        }
+        if (size == 3 && op != NEON_3R_LOGIC) {
+            /* 64-bit element instructions. */
             for (pass = 0; pass < (q ? 2 : 1); pass++) {
                 neon_load_reg64(cpu_V0, rn + pass);
                 neon_load_reg64(cpu_V1, rm + pass);
                 switch (op) {
-                case 1: /* VQADD */
+                case NEON_3R_VQADD:
                     if (u) {
                         gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
                     } else {
                         gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
                     }
                     break;
-                case 5: /* VQSUB */
+                case NEON_3R_VQSUB:
                     if (u) {
                         gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
                     } else {
                         gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
                     }
                     break;
-                case 8: /* VSHL */
+                case NEON_3R_VSHL:
                     if (u) {
                         gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
                         gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
-                case 9: /* VQSHL */
+                case NEON_3R_VQSHL:
                     if (u) {
                         gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
                         gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
-                case 10: /* VRSHL */
+                case NEON_3R_VRSHL:
                     if (u) {
                         gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
                         gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
-                case 11: /* VQRSHL */
+                case NEON_3R_VQRSHL:
                     if (u) {
                         gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
                         gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
-                case 16:
+                case NEON_3R_VADD_VSUB:
                     if (u) {
                         tcg_gen_sub_i64(CPU_V001);
                     } else {
@@ -4341,10 +4411,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             return 0;
         }
         switch (op) {
-        case 8: /* VSHL */
-        case 9: /* VQSHL */
-        case 10: /* VRSHL */
-        case 11: /* VQRSHL */
+        case NEON_3R_VSHL:
+        case NEON_3R_VQSHL:
+        case NEON_3R_VRSHL:
+        case NEON_3R_VQRSHL:
             {
                 int rtmp;
                 /* Shift instruction operands are reversed.  */
@@ -4354,15 +4424,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 pairwise = 0;
             }
             break;
-        case 20: /* VPMAX */
-        case 21: /* VPMIN */
-        case 23: /* VPADD */
+        case NEON_3R_VPMAX:
+        case NEON_3R_VPMIN:
+        case NEON_3R_VPADD:
             pairwise = 1;
             break;
-        case 26: /* VPADD (float) */
+        case NEON_3R_FLOAT_ARITH: /* VADD, VSUB, VPADD, VABD (float) */
             pairwise = (u && size < 2);
             break;
-        case 30: /* VPMIN/VPMAX (float) */
+        case NEON_3R_FLOAT_MINMAX: /* VPMIN/VPMAX (float) */
             pairwise = u;
             break;
         default:
@@ -4391,16 +4461,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             tmp2 = neon_load_reg(rm, pass);
         }
         switch (op) {
-        case 0: /* VHADD */
+        case NEON_3R_VHADD:
             GEN_NEON_INTEGER_OP(hadd);
             break;
-        case 1: /* VQADD */
+        case NEON_3R_VQADD:
             GEN_NEON_INTEGER_OP(qadd);
             break;
-        case 2: /* VRHADD */
+        case NEON_3R_VRHADD:
             GEN_NEON_INTEGER_OP(rhadd);
             break;
-        case 3: /* Logic ops.  */
+        case NEON_3R_LOGIC: /* Logic ops.  */
             switch ((u << 2) | size) {
             case 0: /* VAND */
                 tcg_gen_and_i32(tmp, tmp, tmp2);
@@ -4434,81 +4504,80 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 break;
             }
             break;
-        case 4: /* VHSUB */
+        case NEON_3R_VHSUB:
             GEN_NEON_INTEGER_OP(hsub);
             break;
-        case 5: /* VQSUB */
+        case NEON_3R_VQSUB:
             GEN_NEON_INTEGER_OP(qsub);
             break;
-        case 6: /* VCGT */
+        case NEON_3R_VCGT:
             GEN_NEON_INTEGER_OP(cgt);
             break;
-        case 7: /* VCGE */
+        case NEON_3R_VCGE:
             GEN_NEON_INTEGER_OP(cge);
             break;
-        case 8: /* VSHL */
+        case NEON_3R_VSHL:
             GEN_NEON_INTEGER_OP(shl);
             break;
-        case 9: /* VQSHL */
+        case NEON_3R_VQSHL:
             GEN_NEON_INTEGER_OP(qshl);
             break;
-        case 10: /* VRSHL */
+        case NEON_3R_VRSHL:
             GEN_NEON_INTEGER_OP(rshl);
             break;
-        case 11: /* VQRSHL */
+        case NEON_3R_VQRSHL:
             GEN_NEON_INTEGER_OP(qrshl);
             break;
-        case 12: /* VMAX */
+        case NEON_3R_VMAX:
             GEN_NEON_INTEGER_OP(max);
             break;
-        case 13: /* VMIN */
+        case NEON_3R_VMIN:
             GEN_NEON_INTEGER_OP(min);
             break;
-        case 14: /* VABD */
+        case NEON_3R_VABD:
             GEN_NEON_INTEGER_OP(abd);
             break;
-        case 15: /* VABA */
+        case NEON_3R_VABA:
             GEN_NEON_INTEGER_OP(abd);
             tcg_temp_free_i32(tmp2);
             tmp2 = neon_load_reg(rd, pass);
             gen_neon_add(size, tmp, tmp2);
             break;
-        case 16:
+        case NEON_3R_VADD_VSUB:
             if (!u) { /* VADD */
-                if (gen_neon_add(size, tmp, tmp2))
-                    return 1;
+                gen_neon_add(size, tmp, tmp2);
             } else { /* VSUB */
                 switch (size) {
                 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
                 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
                 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
             }
             break;
-        case 17:
+        case NEON_3R_VTST_VCEQ:
             if (!u) { /* VTST */
                 switch (size) {
                 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
                 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
                 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
             } else { /* VCEQ */
                 switch (size) {
                 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
                 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
                 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
             }
             break;
-        case 18: /* Multiply.  */
+        case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
             switch (size) {
             case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
             case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
             case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
-            default: return 1;
+            default: abort();
             }
             tcg_temp_free_i32(tmp2);
             tmp2 = neon_load_reg(rd, pass);
@@ -4518,7 +4587,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 gen_neon_add(size, tmp, tmp2);
             }
             break;
-        case 19: /* VMUL */
+        case NEON_3R_VMUL:
             if (u) { /* polynomial */
                 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
             } else { /* Integer */
@@ -4526,42 +4595,42 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
                 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
                 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
             }
             break;
-        case 20: /* VPMAX */
+        case NEON_3R_VPMAX:
             GEN_NEON_INTEGER_OP(pmax);
             break;
-        case 21: /* VPMIN */
+        case NEON_3R_VPMIN:
             GEN_NEON_INTEGER_OP(pmin);
             break;
-        case 22: /* Hultiply high.  */
+        case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
             if (!u) { /* VQDMULH */
                 switch (size) {
                 case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
                 case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
-            } else { /* VQRDHMUL */
+            } else { /* VQRDMULH */
                 switch (size) {
                 case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
                 case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
-                default: return 1;
+                default: abort();
                 }
             }
             break;
-        case 23: /* VPADD */
+        case NEON_3R_VPADD:
             if (u)
                 return 1;
             switch (size) {
             case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
             case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
             case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
-            default: return 1;
+            default: abort();
             }
             break;
-        case 26: /* Floating point arithnetic.  */
+        case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
             switch ((u << 2) | size) {
             case 0: /* VADD */
                 gen_helper_neon_add_f32(tmp, tmp, tmp2);
@@ -4576,10 +4645,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
                 break;
             default:
-                return 1;
+                abort();
             }
             break;
-        case 27: /* Float multiply.  */
+        case NEON_3R_FLOAT_MULTIPLY:
             gen_helper_neon_mul_f32(tmp, tmp, tmp2);
             if (!u) {
                 tcg_temp_free_i32(tmp2);
@@ -4591,7 +4660,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 }
             }
             break;
-        case 28: /* Float compare.  */
+        case NEON_3R_FLOAT_CMP:
             if (!u) {
                 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
             } else {
@@ -4601,7 +4670,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
             }
             break;
-        case 29: /* Float compare absolute.  */
+        case NEON_3R_FLOAT_ACMP:
             if (!u)
                 return 1;
             if (size == 0)
@@ -4609,13 +4678,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             else
                 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
             break;
-        case 30: /* Float min/max.  */
+        case NEON_3R_FLOAT_MINMAX:
             if (size == 0)
                 gen_helper_neon_max_f32(tmp, tmp, tmp2);
             else
                 gen_helper_neon_min_f32(tmp, tmp, tmp2);
             break;
-        case 31:
+        case NEON_3R_VRECPS_VRSQRTS:
             if (size == 0)
                 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
             else
commit 54f8e61d5bf8c80c407d8d6ea46ead816c029512
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Tue Apr 12 17:27:44 2011 +0800

    fix acpi regression
    
    This bug is introduced by commit 23910d3f.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi.c b/hw/acpi.c
index e372474..ad40fb4 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -355,7 +355,7 @@ static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
     if (addr < gpe->len / 2) {
         cur = gpe->sts + addr;
     } else if (addr < gpe->len) {
-        cur = gpe->en + addr;
+        cur = gpe->en + addr - gpe->len / 2;
     } else {
         abort();
     }
commit 54f7b4a396d00522d99c685562a54725a1b52e40
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 10 18:23:39 2011 +0200

    Replace cpu_physical_memory_rw were possible
    
    Using cpu_physical_memory_read, cpu_physical_memory_write and ldub_phys
    improves readability and allows removing some type casts.
    
    lduw_phys and ldl_phys were not used because both require aligned
    addresses. Therefore it is not possible to simply replace existing
    calls by one of these functions.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/disas.c b/disas.c
index 17b4ce4..223606c 100644
--- a/disas.c
+++ b/disas.c
@@ -345,7 +345,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
                      struct disassemble_info *info)
 {
     if (monitor_disas_is_physical) {
-        cpu_physical_memory_rw(memaddr, myaddr, length, 0);
+        cpu_physical_memory_read(memaddr, myaddr, length);
     } else {
         cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
     }
diff --git a/exec.c b/exec.c
index e8f1eeb..b1ee52a 100644
--- a/exec.c
+++ b/exec.c
@@ -3932,7 +3932,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
             bounce.addr = addr;
             bounce.len = l;
             if (!is_write) {
-                cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
+                cpu_physical_memory_read(addr, bounce.buffer, l);
             }
             ptr = bounce.buffer;
         } else {
diff --git a/hw/rc4030.c b/hw/rc4030.c
index d30230a..6563336 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -307,7 +307,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
         if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) {
             target_phys_addr_t dest = s->cache_ptag & ~0x1;
             dest += (s->cache_maint & 0x3) << 3;
-            cpu_physical_memory_rw(dest, (uint8_t*)&val, 4, 1);
+            cpu_physical_memory_write(dest, &val, 4);
         }
         break;
     /* Remote Speed Registers */
@@ -704,7 +704,7 @@ void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, i
         entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
         /* XXX: not sure. should we really use only lowest bits? */
         entry_addr &= 0x7fffffff;
-        cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(entry), 0);
+        cpu_physical_memory_read(entry_addr, &entry, sizeof(entry));
 
         /* Read/write data at right place */
         phys_addr = entry.frame + (addr & (DMA_PAGESIZE - 1));
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 60e0135..175e5cb 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -233,7 +233,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
         dev->vdev->get_config(dev->vdev, dev->vdev->config);
     }
 
-    cpu_physical_memory_rw(cur_offs, dev->vdev->config, dev->vdev->config_len, 1);
+    cpu_physical_memory_write(cur_offs,
+                              dev->vdev->config, dev->vdev->config_len);
     cur_offs += dev->vdev->config_len;
 }
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 850422f..d429f10 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -230,8 +230,8 @@ static void s390_init(ram_addr_t ram_size,
     }
 
     if (kernel_cmdline) {
-        cpu_physical_memory_rw(KERN_PARM_AREA, (uint8_t *)kernel_cmdline,
-                               strlen(kernel_cmdline), 1);
+        cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline,
+                                  strlen(kernel_cmdline));
     }
 
     /* Create VirtIO network adapters */
diff --git a/hw/sm501_template.h b/hw/sm501_template.h
index d1ceef9..2d4a3d8 100644
--- a/hw/sm501_template.h
+++ b/hw/sm501_template.h
@@ -120,7 +120,7 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State * s, int crt,
 
         /* get pixel value */
         if (i % 4 == 0) {
-            cpu_physical_memory_rw(cursor_addr, &bitset, 1, 0);
+            bitset = ldub_phys(cursor_addr);
             cursor_addr++;
         }
         v = bitset & 3;
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index d2b14f7..0ad4f55 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -427,7 +427,7 @@ static inline int get_dwords(OHCIState *ohci,
     addr += ohci->localmem_base;
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0);
+        cpu_physical_memory_read(addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -444,7 +444,7 @@ static inline int put_dwords(OHCIState *ohci,
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
-        cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1);
+        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -459,7 +459,7 @@ static inline int get_words(OHCIState *ohci,
     addr += ohci->localmem_base;
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0);
+        cpu_physical_memory_read(addr, buf, sizeof(*buf));
         *buf = le16_to_cpu(*buf);
     }
 
@@ -476,7 +476,7 @@ static inline int put_words(OHCIState *ohci,
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint16_t tmp = cpu_to_le16(*buf);
-        cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1);
+        cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -504,8 +504,7 @@ static inline int ohci_read_iso_td(OHCIState *ohci,
 static inline int ohci_read_hcca(OHCIState *ohci,
                                  uint32_t addr, struct ohci_hcca *hcca)
 {
-    cpu_physical_memory_rw(addr + ohci->localmem_base,
-                           (uint8_t *)hcca, sizeof(*hcca), 0);
+    cpu_physical_memory_read(addr + ohci->localmem_base, hcca, sizeof(*hcca));
     return 1;
 }
 
@@ -531,8 +530,7 @@ static inline int ohci_put_iso_td(OHCIState *ohci,
 static inline int ohci_put_hcca(OHCIState *ohci,
                                 uint32_t addr, struct ohci_hcca *hcca)
 {
-    cpu_physical_memory_rw(addr + ohci->localmem_base,
-                           (uint8_t *)hcca, sizeof(*hcca), 1);
+    cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca));
     return 1;
 }
 
diff --git a/monitor.c b/monitor.c
index 07186ca..5f3bc72 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1429,7 +1429,7 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
         if (l > line_size)
             l = line_size;
         if (is_physical) {
-            cpu_physical_memory_rw(addr, buf, l, 0);
+            cpu_physical_memory_read(addr, buf, l);
         } else {
             env = mon_get_cpu();
             if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
@@ -1605,7 +1605,7 @@ static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
         l = sizeof(buf);
         if (l > size)
             l = size;
-        cpu_physical_memory_rw(addr, buf, l, 0);
+        cpu_physical_memory_read(addr, buf, l);
         if (fwrite(buf, 1, l, f) != l) {
             monitor_printf(mon, "fwrite() error in do_physical_memory_save\n");
             goto exit;
@@ -1625,17 +1625,16 @@ exit:
 static void do_sum(Monitor *mon, const QDict *qdict)
 {
     uint32_t addr;
-    uint8_t buf[1];
     uint16_t sum;
     uint32_t start = qdict_get_int(qdict, "start");
     uint32_t size = qdict_get_int(qdict, "size");
 
     sum = 0;
     for(addr = start; addr < (start + size); addr++) {
-        cpu_physical_memory_rw(addr, buf, 1, 0);
+        uint8_t val = ldub_phys(addr);
         /* BSD sum algorithm ('sum' Unix command) */
         sum = (sum >> 1) | (sum << 15);
-        sum += buf[0];
+        sum += val;
     }
     monitor_printf(mon, "%05d\n", sum);
 }
commit b8b79323d0f26959237fdb80053cd48a750e3482
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Mar 26 21:11:05 2011 +0100

    monitor: Remove some type casts which are no longer needed
    
    All other type casts in calls of cpu_physical_memory_read are
    used by hardware emulations and will be fixed by separate patches.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/monitor.c b/monitor.c
index f1a08dc..07186ca 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2026,7 +2026,7 @@ static void tlb_info_32(Monitor *mon, CPUState *env)
 
     pgd = env->cr[3] & ~0xfff;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
+        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
@@ -2034,8 +2034,7 @@ static void tlb_info_32(Monitor *mon, CPUState *env)
                 print_pte(mon, (l1 << 22), pde, ~((1 << 21) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
-                                             (uint8_t *)&pte, 4);
+                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
                     pte = le32_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
                         print_pte(mon, (l1 << 22) + (l2 << 12),
@@ -2056,13 +2055,12 @@ static void tlb_info_pae32(Monitor *mon, CPUState *env)
 
     pdp_addr = env->cr[3] & ~0x1f;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, (uint8_t *)&pdpe, 8);
+        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8,
-                                         (uint8_t *)&pde, 8);
+                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 if (pde & PG_PRESENT_MASK) {
                     if (pde & PG_PSE_MASK) {
@@ -2072,8 +2070,7 @@ static void tlb_info_pae32(Monitor *mon, CPUState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8,
-                                                     (uint8_t *)&pte, 8);
+                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
                             pte = le64_to_cpu(pte);
                             if (pte & PG_PRESENT_MASK) {
                                 print_pte(mon, (l1 << 30 ) + (l2 << 21)
@@ -2098,13 +2095,12 @@ static void tlb_info_64(Monitor *mon, CPUState *env)
 
     pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
     for (l1 = 0; l1 < 512; l1++) {
-        cpu_physical_memory_read(pml4_addr + l1 * 8, (uint8_t *)&pml4e, 8);
+        cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
         pml4e = le64_to_cpu(pml4e);
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pdp_addr + l2 * 8, (uint8_t *)&pdpe,
-                                         8);
+                cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
                 pdpe = le64_to_cpu(pdpe);
                 if (pdpe & PG_PRESENT_MASK) {
                     if (pdpe & PG_PSE_MASK) {
@@ -2114,8 +2110,7 @@ static void tlb_info_64(Monitor *mon, CPUState *env)
                     } else {
                         pd_addr = pdpe & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pd_addr + l3 * 8,
-                                                     (uint8_t *)&pde, 8);
+                            cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
                             pde = le64_to_cpu(pde);
                             if (pde & PG_PRESENT_MASK) {
                                 if (pde & PG_PSE_MASK) {
@@ -2128,8 +2123,7 @@ static void tlb_info_64(Monitor *mon, CPUState *env)
                                     for (l4 = 0; l4 < 512; l4++) {
                                         cpu_physical_memory_read(pt_addr
                                                                  + l4 * 8,
-                                                                 (uint8_t *)&pte,
-                                                                 8);
+                                                                 &pte, 8);
                                         pte = le64_to_cpu(pte);
                                         if (pte & PG_PRESENT_MASK) {
                                             print_pte(mon, (l1 << 39) +
@@ -2207,7 +2201,7 @@ static void mem_info_32(Monitor *mon, CPUState *env)
     last_prot = 0;
     start = -1;
     for(l1 = 0; l1 < 1024; l1++) {
-        cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
+        cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
         pde = le32_to_cpu(pde);
         end = l1 << 22;
         if (pde & PG_PRESENT_MASK) {
@@ -2216,8 +2210,7 @@ static void mem_info_32(Monitor *mon, CPUState *env)
                 mem_print(mon, &start, &last_prot, end, prot);
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
-                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
-                                             (uint8_t *)&pte, 4);
+                    cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
                     pte = le32_to_cpu(pte);
                     end = (l1 << 22) + (l2 << 12);
                     if (pte & PG_PRESENT_MASK) {
@@ -2246,14 +2239,13 @@ static void mem_info_pae32(Monitor *mon, CPUState *env)
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 4; l1++) {
-        cpu_physical_memory_read(pdp_addr + l1 * 8, (uint8_t *)&pdpe, 8);
+        cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
         pdpe = le64_to_cpu(pdpe);
         end = l1 << 30;
         if (pdpe & PG_PRESENT_MASK) {
             pd_addr = pdpe & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pd_addr + l2 * 8,
-                                         (uint8_t *)&pde, 8);
+                cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
                 pde = le64_to_cpu(pde);
                 end = (l1 << 30) + (l2 << 21);
                 if (pde & PG_PRESENT_MASK) {
@@ -2264,8 +2256,7 @@ static void mem_info_pae32(Monitor *mon, CPUState *env)
                     } else {
                         pt_addr = pde & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pt_addr + l3 * 8,
-                                                     (uint8_t *)&pte, 8);
+                            cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
                             pte = le64_to_cpu(pte);
                             end = (l1 << 30) + (l2 << 21) + (l3 << 12);
                             if (pte & PG_PRESENT_MASK) {
@@ -2302,14 +2293,13 @@ static void mem_info_64(Monitor *mon, CPUState *env)
     last_prot = 0;
     start = -1;
     for (l1 = 0; l1 < 512; l1++) {
-        cpu_physical_memory_read(pml4_addr + l1 * 8, (uint8_t *)&pml4e, 8);
+        cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
         pml4e = le64_to_cpu(pml4e);
         end = l1 << 39;
         if (pml4e & PG_PRESENT_MASK) {
             pdp_addr = pml4e & 0x3fffffffff000ULL;
             for (l2 = 0; l2 < 512; l2++) {
-                cpu_physical_memory_read(pdp_addr + l2 * 8, (uint8_t *)&pdpe,
-                                         8);
+                cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
                 pdpe = le64_to_cpu(pdpe);
                 end = (l1 << 39) + (l2 << 30);
                 if (pdpe & PG_PRESENT_MASK) {
@@ -2320,8 +2310,7 @@ static void mem_info_64(Monitor *mon, CPUState *env)
                     } else {
                         pd_addr = pdpe & 0x3fffffffff000ULL;
                         for (l3 = 0; l3 < 512; l3++) {
-                            cpu_physical_memory_read(pd_addr + l3 * 8,
-                                                     (uint8_t *)&pde, 8);
+                            cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
                             pde = le64_to_cpu(pde);
                             end = (l1 << 39) + (l2 << 30) + (l3 << 21);
                             if (pde & PG_PRESENT_MASK) {
@@ -2334,8 +2323,7 @@ static void mem_info_64(Monitor *mon, CPUState *env)
                                     for (l4 = 0; l4 < 512; l4++) {
                                         cpu_physical_memory_read(pt_addr
                                                                  + l4 * 8,
-                                                                 (uint8_t *)&pte,
-                                                                 8);
+                                                                 &pte, 8);
                                         pte = le64_to_cpu(pte);
                                         end = (l1 << 39) + (l2 << 30) +
                                             (l3 << 21) + (l4 << 12);
commit 71d2b725e1f38162872b198992a61fa460978d77
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Mar 26 21:06:56 2011 +0100

    exec: Remove a type cast which is no longer needed
    
    All other type casts in calls of cpu_physical_memory_write are
    used by hardware emulations and will be fixed by separate patches.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/exec.c b/exec.c
index 983c0db..e8f1eeb 100644
--- a/exec.c
+++ b/exec.c
@@ -4253,7 +4253,7 @@ void stw_phys(target_phys_addr_t addr, uint32_t val)
 void stq_phys(target_phys_addr_t addr, uint64_t val)
 {
     val = tswap64(val);
-    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
+    cpu_physical_memory_write(addr, &val, 8);
 }
 
 /* virtual memory access for debug (includes writing to ROM) */
commit 3bad98147f84f2606afe2afb9d80ea15d3e1c39f
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 10 17:28:56 2011 +0200

    cpu-common: Modify cpu_physical_memory_read and cpu_physical_memory_write
    
    A lot of calls don't operate on bytes but on words or on structured data.
    So instead of a pointer to uint8_t, a void pointer is the better choice.
    
    This allows removing many type casts.
    
    (Some very early implementations of memcpy used char pointers
    which were replaced by void pointers for the same reason).
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-common.h b/cpu-common.h
index ef4e8da..96c02ae 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -68,14 +68,14 @@ void cpu_unregister_io_memory(int table_address);
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                             int len, int is_write);
 static inline void cpu_physical_memory_read(target_phys_addr_t addr,
-                                            uint8_t *buf, int len)
+                                            void *buf, int len)
 {
     cpu_physical_memory_rw(addr, buf, len, 0);
 }
 static inline void cpu_physical_memory_write(target_phys_addr_t addr,
-                                             const uint8_t *buf, int len)
+                                             const void *buf, int len)
 {
-    cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
+    cpu_physical_memory_rw(addr, (void *)buf, len, 1);
 }
 void *cpu_physical_memory_map(target_phys_addr_t addr,
                               target_phys_addr_t *plen,
commit f50ee4e0749604373bfd3bf3bb1d94c28787a378
Author: Michael Walle <michael at walle.cc>
Date:   Sat Apr 9 23:13:20 2011 +0200

    configure: disable opengl per default
    
    There is a bug in nvidia's binary GPU driver, which causes a segmentation
    fault if linked to libGL.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index ed4d951..da2da04 100755
--- a/configure
+++ b/configure
@@ -177,6 +177,7 @@ spice=""
 rbd=""
 smartcard=""
 smartcard_nss=""
+opengl="no"
 
 # parse CC options first
 for opt do
commit 7dae117a58dc89af15e3832fe435a4037c83d3d2
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Apr 10 21:09:12 2011 +0200

    target-ppc: remove #ifdef FLOAT128
    
    Now that PPC defaults to softfloat which always provides float128
    support, there is no need to keep two version of the code, depending if
    float128 support is available or not. Suggested by Peter Maydell.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 5882bec..8c993a1 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1287,7 +1287,6 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             /* sNaN operation */
             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
         }
-#ifdef FLOAT128
         /* This is the way the PowerPC specification defines it */
         float128 ft0_128, ft1_128;
 
@@ -1303,10 +1302,6 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
         }
-#else
-        /* This is OK on x86 hosts */
-        farg1.d = (farg1.d * farg2.d) + farg3.d;
-#endif
     }
 
     return farg1.ll;
@@ -1332,7 +1327,6 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             /* sNaN operation */
             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
         }
-#ifdef FLOAT128
         /* This is the way the PowerPC specification defines it */
         float128 ft0_128, ft1_128;
 
@@ -1348,10 +1342,6 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
         }
-#else
-        /* This is OK on x86 hosts */
-        farg1.d = (farg1.d * farg2.d) - farg3.d;
-#endif
     }
     return farg1.ll;
 }
@@ -1376,7 +1366,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             /* sNaN operation */
             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
         }
-#ifdef FLOAT128
         /* This is the way the PowerPC specification defines it */
         float128 ft0_128, ft1_128;
 
@@ -1392,10 +1381,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
         }
-#else
-        /* This is OK on x86 hosts */
-        farg1.d = (farg1.d * farg2.d) + farg3.d;
-#endif
         if (likely(!float64_is_any_nan(farg1.d))) {
             farg1.d = float64_chs(farg1.d);
         }
@@ -1423,7 +1408,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             /* sNaN operation */
             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
         }
-#ifdef FLOAT128
         /* This is the way the PowerPC specification defines it */
         float128 ft0_128, ft1_128;
 
@@ -1439,10 +1423,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
             ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
         }
-#else
-        /* This is OK on x86 hosts */
-        farg1.d = (farg1.d * farg2.d) - farg3.d;
-#endif
         if (likely(!float64_is_any_nan(farg1.d))) {
             farg1.d = float64_chs(farg1.d);
         }
commit d6c424c56e0e9064448d04c271625c8ac696ae50
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Apr 10 21:09:12 2011 +0200

    target-sh4: get rid of CPU_{Float,Double}U
    
    SH4 is always using softfloat, so it's possible to have helpers directly
    taking float32 or float64 value. This allow to get rid of conversions
    through CPU_{Float,Double}U.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 2e52768..95e3c7c 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -23,31 +23,31 @@ DEF_HELPER_2(macw, void, i32, i32)
 
 DEF_HELPER_1(ld_fpscr, void, i32)
 
-DEF_HELPER_1(fabs_FT, i32, i32)
-DEF_HELPER_1(fabs_DT, i64, i64)
-DEF_HELPER_2(fadd_FT, i32, i32, i32)
-DEF_HELPER_2(fadd_DT, i64, i64, i64)
-DEF_HELPER_1(fcnvsd_FT_DT, i64, i32)
-DEF_HELPER_1(fcnvds_DT_FT, i32, i64)
+DEF_HELPER_1(fabs_FT, f32, f32)
+DEF_HELPER_1(fabs_DT, f64, f64)
+DEF_HELPER_2(fadd_FT, f32, f32, f32)
+DEF_HELPER_2(fadd_DT, f64, f64, f64)
+DEF_HELPER_1(fcnvsd_FT_DT, f64, f32)
+DEF_HELPER_1(fcnvds_DT_FT, f32, f64)
 
-DEF_HELPER_2(fcmp_eq_FT, void, i32, i32)
-DEF_HELPER_2(fcmp_eq_DT, void, i64, i64)
-DEF_HELPER_2(fcmp_gt_FT, void, i32, i32)
-DEF_HELPER_2(fcmp_gt_DT, void, i64, i64)
-DEF_HELPER_2(fdiv_FT, i32, i32, i32)
-DEF_HELPER_2(fdiv_DT, i64, i64, i64)
-DEF_HELPER_1(float_FT, i32, i32)
-DEF_HELPER_1(float_DT, i64, i32)
-DEF_HELPER_3(fmac_FT, i32, i32, i32, i32)
-DEF_HELPER_2(fmul_FT, i32, i32, i32)
-DEF_HELPER_2(fmul_DT, i64, i64, i64)
-DEF_HELPER_1(fneg_T, i32, i32)
-DEF_HELPER_2(fsub_FT, i32, i32, i32)
-DEF_HELPER_2(fsub_DT, i64, i64, i64)
-DEF_HELPER_1(fsqrt_FT, i32, i32)
-DEF_HELPER_1(fsqrt_DT, i64, i64)
-DEF_HELPER_1(ftrc_FT, i32, i32)
-DEF_HELPER_1(ftrc_DT, i32, i64)
+DEF_HELPER_2(fcmp_eq_FT, void, f32, f32)
+DEF_HELPER_2(fcmp_eq_DT, void, f64, f64)
+DEF_HELPER_2(fcmp_gt_FT, void, f32, f32)
+DEF_HELPER_2(fcmp_gt_DT, void, f64, f64)
+DEF_HELPER_2(fdiv_FT, f32, f32, f32)
+DEF_HELPER_2(fdiv_DT, f64, f64, f64)
+DEF_HELPER_1(float_FT, f32, i32)
+DEF_HELPER_1(float_DT, f64, i32)
+DEF_HELPER_3(fmac_FT, f32, f32, f32, f32)
+DEF_HELPER_2(fmul_FT, f32, f32, f32)
+DEF_HELPER_2(fmul_DT, f64, f64, f64)
+DEF_HELPER_1(fneg_T, f32, f32)
+DEF_HELPER_2(fsub_FT, f32, f32, f32)
+DEF_HELPER_2(fsub_DT, f64, f64, f64)
+DEF_HELPER_1(fsqrt_FT, f32, f32)
+DEF_HELPER_1(fsqrt_DT, f64, f64)
+DEF_HELPER_1(ftrc_FT, i32, f32)
+DEF_HELPER_1(ftrc_DT, i32, f64)
 DEF_HELPER_2(fipr, void, i32, i32)
 DEF_HELPER_1(ftrv, void, i32)
 
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index b8f4ca2..c127860 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -487,53 +487,38 @@ static void update_fpscr(void *retaddr)
     }
 }
 
-uint32_t helper_fabs_FT(uint32_t t0)
+float32 helper_fabs_FT(float32 t0)
 {
-    CPU_FloatU f;
-    f.l = t0;
-    f.f = float32_abs(f.f);
-    return f.l;
+    return float32_abs(t0);
 }
 
-uint64_t helper_fabs_DT(uint64_t t0)
+float64 helper_fabs_DT(float64 t0)
 {
-    CPU_DoubleU d;
-    d.ll = t0;
-    d.d = float64_abs(d.d);
-    return d.ll;
+    return float64_abs(t0);
 }
 
-uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
+float32 helper_fadd_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
-    f0.l = t0;
-    f1.l = t1;
     set_float_exception_flags(0, &env->fp_status);
-    f0.f = float32_add(f0.f, f1.f, &env->fp_status);
+    t0 = float32_add(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return f0.l;
+    return t0;
 }
 
-uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
+float64 helper_fadd_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
-    d0.ll = t0;
-    d1.ll = t1;
     set_float_exception_flags(0, &env->fp_status);
-    d0.d = float64_add(d0.d, d1.d, &env->fp_status);
+    t0 = float64_add(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return d0.ll;
+    return t0;
 }
 
-void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
+void helper_fcmp_eq_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
     int relation;
-    f0.l = t0;
-    f1.l = t1;
 
     set_float_exception_flags(0, &env->fp_status);
-    relation = float32_compare(f0.f, f1.f, &env->fp_status);
+    relation = float32_compare(t0, t1, &env->fp_status);
     if (unlikely(relation == float_relation_unordered)) {
         update_fpscr(GETPC());
     } else if (relation == float_relation_equal) {
@@ -543,15 +528,12 @@ void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
     }
 }
 
-void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
+void helper_fcmp_eq_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
     int relation;
-    d0.ll = t0;
-    d1.ll = t1;
 
     set_float_exception_flags(0, &env->fp_status);
-    relation = float64_compare(d0.d, d1.d, &env->fp_status);
+    relation = float64_compare(t0, t1, &env->fp_status);
     if (unlikely(relation == float_relation_unordered)) {
         update_fpscr(GETPC());
     } else if (relation == float_relation_equal) {
@@ -561,15 +543,12 @@ void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
     }
 }
 
-void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
+void helper_fcmp_gt_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
     int relation;
-    f0.l = t0;
-    f1.l = t1;
 
     set_float_exception_flags(0, &env->fp_status);
-    relation = float32_compare(f0.f, f1.f, &env->fp_status);
+    relation = float32_compare(t0, t1, &env->fp_status);
     if (unlikely(relation == float_relation_unordered)) {
         update_fpscr(GETPC());
     } else if (relation == float_relation_greater) {
@@ -579,15 +558,12 @@ void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
     }
 }
 
-void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
+void helper_fcmp_gt_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
     int relation;
-    d0.ll = t0;
-    d1.ll = t1;
 
     set_float_exception_flags(0, &env->fp_status);
-    relation = float64_compare(d0.d, d1.d, &env->fp_status);
+    relation = float64_compare(t0, t1, &env->fp_status);
     if (unlikely(relation == float_relation_unordered)) {
         update_fpscr(GETPC());
     } else if (relation == float_relation_greater) {
@@ -597,176 +573,134 @@ void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
     }
 }
 
-uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
+float64 helper_fcnvsd_FT_DT(float32 t0)
 {
-    CPU_DoubleU d;
-    CPU_FloatU f;
-    f.l = t0;
+    float64 ret;
     set_float_exception_flags(0, &env->fp_status);
-    d.d = float32_to_float64(f.f, &env->fp_status);
+    ret = float32_to_float64(t0, &env->fp_status);
     update_fpscr(GETPC());
-    return d.ll;
+    return ret;
 }
 
-uint32_t helper_fcnvds_DT_FT(uint64_t t0)
+float32 helper_fcnvds_DT_FT(float64 t0)
 {
-    CPU_DoubleU d;
-    CPU_FloatU f;
-    d.ll = t0;
+    float32 ret;
     set_float_exception_flags(0, &env->fp_status);
-    f.f = float64_to_float32(d.d, &env->fp_status);
+    ret = float64_to_float32(t0, &env->fp_status);
     update_fpscr(GETPC());
-    return f.l;
+    return ret;
 }
 
-uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
+float32 helper_fdiv_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
-    f0.l = t0;
-    f1.l = t1;
     set_float_exception_flags(0, &env->fp_status);
-    f0.f = float32_div(f0.f, f1.f, &env->fp_status);
+    t0 = float32_div(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return f0.l;
+    return t0;
 }
 
-uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
+float64 helper_fdiv_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
-    d0.ll = t0;
-    d1.ll = t1;
     set_float_exception_flags(0, &env->fp_status);
-    d0.d = float64_div(d0.d, d1.d, &env->fp_status);
+    t0 = float64_div(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return d0.ll;
+    return t0;
 }
 
-uint32_t helper_float_FT(uint32_t t0)
+float32 helper_float_FT(uint32_t t0)
 {
-    CPU_FloatU f;
-
+    float32 ret;
     set_float_exception_flags(0, &env->fp_status);
-    f.f = int32_to_float32(t0, &env->fp_status);
+    ret = int32_to_float32(t0, &env->fp_status);
     update_fpscr(GETPC());
-
-    return f.l;
+    return ret;
 }
 
-uint64_t helper_float_DT(uint32_t t0)
+float64 helper_float_DT(uint32_t t0)
 {
-    CPU_DoubleU d;
+    float64 ret;
     set_float_exception_flags(0, &env->fp_status);
-    d.d = int32_to_float64(t0, &env->fp_status);
+    ret = int32_to_float64(t0, &env->fp_status);
     update_fpscr(GETPC());
-    return d.ll;
+    return ret;
 }
 
-uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
+float32 helper_fmac_FT(float32 t0, float32 t1, float32 t2)
 {
-    CPU_FloatU f0, f1, f2;
-    f0.l = t0;
-    f1.l = t1;
-    f2.l = t2;
     set_float_exception_flags(0, &env->fp_status);
-    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
-    f0.f = float32_add(f0.f, f2.f, &env->fp_status);
+    t0 = float32_mul(t0, t1, &env->fp_status);
+    t0 = float32_add(t0, t2, &env->fp_status);
     update_fpscr(GETPC());
-
-    return f0.l;
+    return t0;
 }
 
-uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
+float32 helper_fmul_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
-    f0.l = t0;
-    f1.l = t1;
     set_float_exception_flags(0, &env->fp_status);
-    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
+    t0 = float32_mul(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return f0.l;
+    return t0;
 }
 
-uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
+float64 helper_fmul_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
-    d0.ll = t0;
-    d1.ll = t1;
     set_float_exception_flags(0, &env->fp_status);
-    d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
+    t0 = float64_mul(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-
-    return d0.ll;
+    return t0;
 }
 
-uint32_t helper_fneg_T(uint32_t t0)
+float32 helper_fneg_T(float32 t0)
 {
-    CPU_FloatU f;
-    f.l = t0;
-    f.f = float32_chs(f.f);
-    return f.l;
+    return float32_chs(t0);
 }
 
-uint32_t helper_fsqrt_FT(uint32_t t0)
+float32 helper_fsqrt_FT(float32 t0)
 {
-    CPU_FloatU f;
-    f.l = t0;
     set_float_exception_flags(0, &env->fp_status);
-    f.f = float32_sqrt(f.f, &env->fp_status);
+    t0 = float32_sqrt(t0, &env->fp_status);
     update_fpscr(GETPC());
-    return f.l;
+    return t0;
 }
 
-uint64_t helper_fsqrt_DT(uint64_t t0)
+float64 helper_fsqrt_DT(float64 t0)
 {
-    CPU_DoubleU d;
-    d.ll = t0;
     set_float_exception_flags(0, &env->fp_status);
-    d.d = float64_sqrt(d.d, &env->fp_status);
+    t0 = float64_sqrt(t0, &env->fp_status);
     update_fpscr(GETPC());
-    return d.ll;
+    return t0;
 }
 
-uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
+float32 helper_fsub_FT(float32 t0, float32 t1)
 {
-    CPU_FloatU f0, f1;
-    f0.l = t0;
-    f1.l = t1;
     set_float_exception_flags(0, &env->fp_status);
-    f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
+    t0 = float32_sub(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return f0.l;
+    return t0;
 }
 
-uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
+float64 helper_fsub_DT(float64 t0, float64 t1)
 {
-    CPU_DoubleU d0, d1;
-
-    d0.ll = t0;
-    d1.ll = t1;
     set_float_exception_flags(0, &env->fp_status);
-    d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
+    t0 = float64_sub(t0, t1, &env->fp_status);
     update_fpscr(GETPC());
-    return d0.ll;
+    return t0;
 }
 
-uint32_t helper_ftrc_FT(uint32_t t0)
+uint32_t helper_ftrc_FT(float32 t0)
 {
-    CPU_FloatU f;
     uint32_t ret;
-    f.l = t0;
     set_float_exception_flags(0, &env->fp_status);
-    ret = float32_to_int32_round_to_zero(f.f, &env->fp_status);
+    ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
     update_fpscr(GETPC());
     return ret;
 }
 
-uint32_t helper_ftrc_DT(uint64_t t0)
+uint32_t helper_ftrc_DT(float64 t0)
 {
-    CPU_DoubleU d;
     uint32_t ret;
-    d.ll = t0;
     set_float_exception_flags(0, &env->fp_status);
-    ret = float64_to_int32_round_to_zero(d.d, &env->fp_status);
+    ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
     update_fpscr(GETPC());
     return ret;
 }
commit d2fbca94223ef573a67d4eb2f27509a9bbb85ca1
Author: Guan Xuetao <gxt at mprc.pku.edu.cn>
Date:   Tue Apr 12 16:27:03 2011 +0800

    unicore32: necessary modifications for other files to support unicore32
    
    Signed-off-by: Guan Xuetao <gxt at mprc.pku.edu.cn>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index a4759ae..ed4d951 100755
--- a/configure
+++ b/configure
@@ -283,7 +283,7 @@ else
 fi
 
 case "$cpu" in
-  alpha|cris|ia64|lm32|m68k|microblaze|ppc|ppc64|sparc64)
+  alpha|cris|ia64|lm32|m68k|microblaze|ppc|ppc64|sparc64|unicore32)
     cpu="$cpu"
   ;;
   i386|i486|i586|i686|i86pc|BePC)
@@ -814,6 +814,9 @@ case "$cpu" in
     hppa*)
            host_guest_base="yes"
            ;;
+    unicore32*)
+           host_guest_base="yes"
+           ;;
 esac
 
 [ -z "$guest_base" ] && guest_base="$host_guest_base"
@@ -1048,6 +1051,7 @@ sh4eb-linux-user \
 sparc-linux-user \
 sparc64-linux-user \
 sparc32plus-linux-user \
+unicore32-linux-user \
 "
     fi
 # the following are Darwin specific
@@ -2633,7 +2637,7 @@ echo "docdir=$docdir" >> $config_host_mak
 echo "confdir=$confdir" >> $config_host_mak
 
 case "$cpu" in
-  i386|x86_64|alpha|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
+  i386|x86_64|alpha|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64|unicore32)
     ARCH=$cpu
   ;;
   armv4b|armv4l)
@@ -3186,6 +3190,9 @@ case "$target_arch2" in
     target_phys_bits=64
     target_long_alignment=8
   ;;
+  unicore32)
+    target_phys_bits=32
+  ;;
   *)
     echo "Unsupported target CPU"
     exit 1
diff --git a/cpu-exec.c b/cpu-exec.c
index 5cc9379..5d6c9a8 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -267,6 +267,7 @@ int cpu_exec(CPUState *env1)
     env->cc_x = (env->sr >> 4) & 1;
 #elif defined(TARGET_ALPHA)
 #elif defined(TARGET_ARM)
+#elif defined(TARGET_UNICORE32)
 #elif defined(TARGET_PPC)
 #elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
@@ -335,6 +336,8 @@ int cpu_exec(CPUState *env1)
                     do_interrupt(env);
 #elif defined(TARGET_ARM)
                     do_interrupt(env);
+#elif defined(TARGET_UNICORE32)
+                    do_interrupt(env);
 #elif defined(TARGET_SH4)
 		    do_interrupt(env);
 #elif defined(TARGET_ALPHA)
@@ -367,7 +370,7 @@ int cpu_exec(CPUState *env1)
                     }
 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
-    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32)
+    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         env->halted = 1;
@@ -514,6 +517,12 @@ int cpu_exec(CPUState *env1)
                         do_interrupt(env);
                         next_tb = 0;
                     }
+#elif defined(TARGET_UNICORE32)
+                    if (interrupt_request & CPU_INTERRUPT_HARD
+                        && !(env->uncached_asr & ASR_I)) {
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #elif defined(TARGET_SH4)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         do_interrupt(env);
@@ -664,6 +673,7 @@ int cpu_exec(CPUState *env1)
     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
+#elif defined(TARGET_UNICORE32)
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_PPC)
 #elif defined(TARGET_LM32)
diff --git a/default-configs/unicore32-linux-user.mak b/default-configs/unicore32-linux-user.mak
new file mode 100644
index 0000000..6aafd21
--- /dev/null
+++ b/default-configs/unicore32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for unicore32-linux-user
diff --git a/elf.h b/elf.h
index 523c972..ffcac7e 100644
--- a/elf.h
+++ b/elf.h
@@ -106,6 +106,8 @@ typedef int64_t  Elf64_Sxword;
 #define EM_H8S          48      /* Hitachi H8S     */
 #define EM_LATTICEMICO32 138    /* LatticeMico32 */
 
+#define EM_UNICORE32    110     /* UniCore32 */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 4b65de6..b110187 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -93,7 +93,7 @@ float16 float16_maybe_silence_nan(float16 a_)
 {
     if (float16_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float16_default_nan;
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -184,7 +184,7 @@ float32 float32_maybe_silence_nan( float32 a_ )
 {
     if (float32_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float32_default_nan;
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -430,7 +430,7 @@ float64 float64_maybe_silence_nan( float64 a_ )
 {
     if (float64_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float64_default_nan;
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -578,7 +578,7 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
 {
     if (floatx80_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a.low = floatx80_default_nan_low;
         a.high = floatx80_default_nan_high;
 #  else
@@ -721,7 +721,7 @@ float128 float128_maybe_silence_nan( float128 a )
 {
     if (float128_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a.low = float128_default_nan_low;
         a.high = float128_default_nan_high;
 #  else
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 90f4250..7abcbe8 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -68,7 +68,7 @@ typedef int64_t int64;
 #define LIT64( a ) a##LL
 #define INLINE static inline
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
 #define SNAN_BIT_IS_ONE		1
 #else
 #define SNAN_BIT_IS_ONE		0
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fe5410e..4c399f8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -339,6 +339,80 @@ enum
 
 #endif
 
+#ifdef TARGET_UNICORE32
+
+#define ELF_START_MMAP          0x80000000
+
+#define elf_check_arch(x)       ((x) == EM_UNICORE32)
+
+#define ELF_CLASS               ELFCLASS32
+#define ELF_DATA                ELFDATA2LSB
+#define ELF_ARCH                EM_UNICORE32
+
+static inline void init_thread(struct target_pt_regs *regs,
+        struct image_info *infop)
+{
+    abi_long stack = infop->start_stack;
+    memset(regs, 0, sizeof(*regs));
+    regs->UC32_REG_asr = 0x10;
+    regs->UC32_REG_pc = infop->entry & 0xfffffffe;
+    regs->UC32_REG_sp = infop->start_stack;
+    /* FIXME - what to for failure of get_user()? */
+    get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */
+    get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */
+    /* XXX: it seems that r0 is zeroed after ! */
+    regs->UC32_REG_00 = 0;
+}
+
+#define ELF_NREG    34
+typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
+
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+{
+    (*regs)[0] = env->regs[0];
+    (*regs)[1] = env->regs[1];
+    (*regs)[2] = env->regs[2];
+    (*regs)[3] = env->regs[3];
+    (*regs)[4] = env->regs[4];
+    (*regs)[5] = env->regs[5];
+    (*regs)[6] = env->regs[6];
+    (*regs)[7] = env->regs[7];
+    (*regs)[8] = env->regs[8];
+    (*regs)[9] = env->regs[9];
+    (*regs)[10] = env->regs[10];
+    (*regs)[11] = env->regs[11];
+    (*regs)[12] = env->regs[12];
+    (*regs)[13] = env->regs[13];
+    (*regs)[14] = env->regs[14];
+    (*regs)[15] = env->regs[15];
+    (*regs)[16] = env->regs[16];
+    (*regs)[17] = env->regs[17];
+    (*regs)[18] = env->regs[18];
+    (*regs)[19] = env->regs[19];
+    (*regs)[20] = env->regs[20];
+    (*regs)[21] = env->regs[21];
+    (*regs)[22] = env->regs[22];
+    (*regs)[23] = env->regs[23];
+    (*regs)[24] = env->regs[24];
+    (*regs)[25] = env->regs[25];
+    (*regs)[26] = env->regs[26];
+    (*regs)[27] = env->regs[27];
+    (*regs)[28] = env->regs[28];
+    (*regs)[29] = env->regs[29];
+    (*regs)[30] = env->regs[30];
+    (*regs)[31] = env->regs[31];
+
+    (*regs)[32] = cpu_asr_read((CPUState *)env);
+    (*regs)[33] = env->regs[0]; /* XXX */
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE               4096
+
+#define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64)
+
+#endif
+
 #ifdef TARGET_SPARC
 #ifdef TARGET_SPARC64
 
diff --git a/linux-user/main.c b/linux-user/main.c
index 9160087..a1e37e4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -816,6 +816,83 @@ void cpu_loop(CPUARMState *env)
 
 #endif
 
+#ifdef TARGET_UNICORE32
+
+void cpu_loop(CPUState *env)
+{
+    int trapnr;
+    unsigned int n, insn;
+    target_siginfo_t info;
+
+    for (;;) {
+        cpu_exec_start(env);
+        trapnr = uc32_cpu_exec(env);
+        cpu_exec_end(env);
+        switch (trapnr) {
+        case UC32_EXCP_PRIV:
+            {
+                /* system call */
+                get_user_u32(insn, env->regs[31] - 4);
+                n = insn & 0xffffff;
+
+                if (n >= UC32_SYSCALL_BASE) {
+                    /* linux syscall */
+                    n -= UC32_SYSCALL_BASE;
+                    if (n == UC32_SYSCALL_NR_set_tls) {
+                            cpu_set_tls(env, env->regs[0]);
+                            env->regs[0] = 0;
+                    } else {
+                        env->regs[0] = do_syscall(env,
+                                                  n,
+                                                  env->regs[0],
+                                                  env->regs[1],
+                                                  env->regs[2],
+                                                  env->regs[3],
+                                                  env->regs[4],
+                                                  env->regs[5]);
+                    }
+                } else {
+                    goto error;
+                }
+            }
+            break;
+        case UC32_EXCP_TRAP:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            /* XXX: check env->error_code */
+            info.si_code = TARGET_SEGV_MAPERR;
+            info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
+            queue_signal(env, info.si_signo, &info);
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.si_signo, &info);
+                }
+            }
+            break;
+        default:
+            goto error;
+        }
+        process_pending_signals(env);
+    }
+
+error:
+    fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
+    cpu_dump_state(env, stderr, fprintf, 0);
+    abort();
+}
+#endif
+
 #ifdef TARGET_SPARC
 #define SPARC64_STACK_BIAS 2047
 
@@ -2925,6 +3002,8 @@ int main(int argc, char **argv, char **envp)
 #endif
 #elif defined(TARGET_ARM)
         cpu_model = "any";
+#elif defined(TARGET_UNICORE32)
+        cpu_model = "any";
 #elif defined(TARGET_M68K)
         cpu_model = "any";
 #elif defined(TARGET_SPARC)
@@ -3227,6 +3306,14 @@ int main(int argc, char **argv, char **envp)
             env->regs[i] = regs->uregs[i];
         }
     }
+#elif defined(TARGET_UNICORE32)
+    {
+        int i;
+        cpu_asr_write(env, regs->uregs[32], 0xffffffff);
+        for (i = 0; i < 32; i++) {
+            env->regs[i] = regs->uregs[i];
+        }
+    }
 #elif defined(TARGET_SPARC)
     {
         int i;
@@ -3367,7 +3454,7 @@ int main(int argc, char **argv, char **envp)
 #error unsupported target CPU
 #endif
 
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
     ts->stack_base = info->start_stack;
     ts->heap_base = info->brk;
     /* This will be filled in on the first SYS_HEAPINFO call.  */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 250814d..f522f5e 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -105,6 +105,9 @@ typedef struct TaskState {
     FPA11 fpa;
     int swi_errno;
 #endif
+#ifdef TARGET_UNICORE32
+    int swi_errno;
+#endif
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
     abi_ulong target_v86;
     struct vm86_saved_state vm86_saved_regs;
@@ -118,7 +121,7 @@ typedef struct TaskState {
 #ifdef TARGET_M68K
     int sim_syscalls;
 #endif
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
     /* Extra fields for semihosted binaries.  */
     uint32_t stack_base;
     uint32_t heap_base;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 702652c..bde8921 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -55,7 +55,7 @@
 #endif
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
-    || defined(TARGET_M68K) || defined(TARGET_CRIS)
+    || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
 
 #define TARGET_IOC_SIZEBITS	14
 #define TARGET_IOC_DIRBITS	2
@@ -315,7 +315,10 @@ struct target_sigaction;
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact);
 
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
+    || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \
+    || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \
+    || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32)
 
 #if defined(TARGET_SPARC)
 #define TARGET_SA_NOCLDSTOP    8u
@@ -1002,7 +1005,8 @@ struct target_winsize {
 #define TARGET_MAP_UNINITIALIZED 0x4000000	/* for anonymous mmap, memory could be uninitialized */
 #endif
 
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
+    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
 struct target_stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
commit 8b5d487d4d35a1a18c3ac48f3dd367fb769592b2
Author: Guan Xuetao <gxt at mprc.pku.edu.cn>
Date:   Tue Apr 12 16:26:27 2011 +0800

    unicore32: add necessry headers in linux-user/unicore32 for unicore32 support
    
    Signed-off-by: Guan Xuetao <gxt at mprc.pku.edu.cn>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/unicore32/syscall.h b/linux-user/unicore32/syscall.h
new file mode 100644
index 0000000..010cdd8
--- /dev/null
+++ b/linux-user/unicore32/syscall.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __UC32_SYSCALL_H__
+#define __UC32_SYSCALL_H__
+struct target_pt_regs {
+    abi_ulong uregs[34];
+};
+
+#define UC32_REG_pc             uregs[31]
+#define UC32_REG_lr             uregs[30]
+#define UC32_REG_sp             uregs[29]
+#define UC32_REG_ip             uregs[28]
+#define UC32_REG_fp             uregs[27]
+#define UC32_REG_26             uregs[26]
+#define UC32_REG_25             uregs[25]
+#define UC32_REG_24             uregs[24]
+#define UC32_REG_23             uregs[23]
+#define UC32_REG_22             uregs[22]
+#define UC32_REG_21             uregs[21]
+#define UC32_REG_20             uregs[20]
+#define UC32_REG_19             uregs[19]
+#define UC32_REG_18             uregs[18]
+#define UC32_REG_17             uregs[17]
+#define UC32_REG_16             uregs[16]
+#define UC32_REG_15             uregs[15]
+#define UC32_REG_14             uregs[14]
+#define UC32_REG_13             uregs[13]
+#define UC32_REG_12             uregs[12]
+#define UC32_REG_11             uregs[11]
+#define UC32_REG_10             uregs[10]
+#define UC32_REG_09             uregs[9]
+#define UC32_REG_08             uregs[8]
+#define UC32_REG_07             uregs[7]
+#define UC32_REG_06             uregs[6]
+#define UC32_REG_05             uregs[5]
+#define UC32_REG_04             uregs[4]
+#define UC32_REG_03             uregs[3]
+#define UC32_REG_02             uregs[2]
+#define UC32_REG_01             uregs[1]
+#define UC32_REG_00             uregs[0]
+#define UC32_REG_asr            uregs[32]
+#define UC32_REG_ORIG_00        uregs[33]
+
+#define UC32_SYSCALL_BASE               0x900000
+#define UC32_SYSCALL_ARCH_BASE          0xf0000
+#define UC32_SYSCALL_NR_set_tls         (UC32_SYSCALL_ARCH_BASE + 5)
+
+#define UNAME_MACHINE "UniCore-II"
+
+#endif /* __UC32_SYSCALL_H__ */
diff --git a/linux-user/unicore32/syscall_nr.h b/linux-user/unicore32/syscall_nr.h
new file mode 100644
index 0000000..9c72d84
--- /dev/null
+++ b/linux-user/unicore32/syscall_nr.h
@@ -0,0 +1,371 @@
+/*
+ * This file contains the system call numbers for UniCore32 oldabi.
+ *
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define TARGET_NR_restart_syscall               0
+#define TARGET_NR_exit                          1
+#define TARGET_NR_fork                          2
+#define TARGET_NR_read                          3
+#define TARGET_NR_write                         4
+#define TARGET_NR_open                          5
+#define TARGET_NR_close                         6
+#define TARGET_NR_waitpid                       7
+#define TARGET_NR_creat                         8
+#define TARGET_NR_link                          9
+#define TARGET_NR_unlink                        10
+#define TARGET_NR_execve                        11
+#define TARGET_NR_chdir                         12
+#define TARGET_NR_time                          13
+#define TARGET_NR_mknod                         14
+#define TARGET_NR_chmod                         15
+#define TARGET_NR_lchown                        16
+#define TARGET_NR_break                         17
+                                                /* 18 */
+#define TARGET_NR_lseek                         19
+#define TARGET_NR_getpid                        20
+#define TARGET_NR_mount                         21
+#define TARGET_NR_umount                        22
+#define TARGET_NR_setuid                        23
+#define TARGET_NR_getuid                        24
+#define TARGET_NR_stime                         25
+#define TARGET_NR_ptrace                        26
+#define TARGET_NR_alarm                         27
+                                                /* 28 */
+#define TARGET_NR_pause                         29
+#define TARGET_NR_utime                         30
+#define TARGET_NR_stty                          31
+#define TARGET_NR_gtty                          32
+#define TARGET_NR_access                        33
+#define TARGET_NR_nice                          34
+#define TARGET_NR_ftime                         35
+#define TARGET_NR_sync                          36
+#define TARGET_NR_kill                          37
+#define TARGET_NR_rename                        38
+#define TARGET_NR_mkdir                         39
+#define TARGET_NR_rmdir                         40
+#define TARGET_NR_dup                           41
+#define TARGET_NR_pipe                          42
+#define TARGET_NR_times                         43
+#define TARGET_NR_prof                          44
+#define TARGET_NR_brk                           45
+#define TARGET_NR_setgid                        46
+#define TARGET_NR_getgid                        47
+#define TARGET_NR_signal                        48
+#define TARGET_NR_geteuid                       49
+#define TARGET_NR_getegid                       50
+#define TARGET_NR_acct                          51
+#define TARGET_NR_umount2                       52
+#define TARGET_NR_lock                          53
+#define TARGET_NR_ioctl                         54
+#define TARGET_NR_fcntl                         55
+#define TARGET_NR_mpx                           56
+#define TARGET_NR_setpgid                       57
+#define TARGET_NR_ulimit                        58
+                                                /* 59 */
+#define TARGET_NR_umask                         60
+#define TARGET_NR_chroot                        61
+#define TARGET_NR_ustat                         62
+#define TARGET_NR_dup2                          63
+#define TARGET_NR_getppid                       64
+#define TARGET_NR_getpgrp                       65
+#define TARGET_NR_setsid                        66
+#define TARGET_NR_sigaction                     67
+#define TARGET_NR_sgetmask                      68
+#define TARGET_NR_ssetmask                      69
+#define TARGET_NR_setreuid                      70
+#define TARGET_NR_setregid                      71
+#define TARGET_NR_sigsuspend                    72
+#define TARGET_NR_sigpending                    73
+#define TARGET_NR_sethostname                   74
+#define TARGET_NR_setrlimit                     75
+#define TARGET_NR_getrlimit                     76
+#define TARGET_NR_getrusage                     77
+#define TARGET_NR_gettimeofday                  78
+#define TARGET_NR_settimeofday                  79
+#define TARGET_NR_getgroups                     80
+#define TARGET_NR_setgroups                     81
+#define TARGET_NR_select                        82
+#define TARGET_NR_symlink                       83
+                                                /* 84 */
+#define TARGET_NR_readlink                      85
+#define TARGET_NR_uselib                        86
+#define TARGET_NR_swapon                        87
+#define TARGET_NR_reboot                        88
+#define TARGET_NR_readdir                       89
+#define TARGET_NR_mmap                          90
+#define TARGET_NR_munmap                        91
+#define TARGET_NR_truncate                      92
+#define TARGET_NR_ftruncate                     93
+#define TARGET_NR_fchmod                        94
+#define TARGET_NR_fchown                        95
+#define TARGET_NR_getpriority                   96
+#define TARGET_NR_setpriority                   97
+#define TARGET_NR_profil                        98
+#define TARGET_NR_statfs                        99
+#define TARGET_NR_fstatfs                       100
+#define TARGET_NR_ioperm                        101
+#define TARGET_NR_socketcall                    102
+#define TARGET_NR_syslog                        103
+#define TARGET_NR_setitimer                     104
+#define TARGET_NR_getitimer                     105
+#define TARGET_NR_stat                          106
+#define TARGET_NR_lstat                         107
+#define TARGET_NR_fstat                         108
+                                                /* 109 */
+                                                /* 110 */
+#define TARGET_NR_vhangup                       111
+#define TARGET_NR_idle                          112
+#define TARGET_NR_syscall                       113
+#define TARGET_NR_wait4                         114
+#define TARGET_NR_swapoff                       115
+#define TARGET_NR_sysinfo                       116
+#define TARGET_NR_ipc                           117
+#define TARGET_NR_fsync                         118
+#define TARGET_NR_sigreturn                     119
+#define TARGET_NR_clone                         120
+#define TARGET_NR_setdomainname                 121
+#define TARGET_NR_uname                         122
+#define TARGET_NR_modify_ldt                    123
+#define TARGET_NR_adjtimex                      124
+#define TARGET_NR_mprotect                      125
+#define TARGET_NR_sigprocmask                   126
+#define TARGET_NR_create_module                 127
+#define TARGET_NR_init_module                   128
+#define TARGET_NR_delete_module                 129
+#define TARGET_NR_get_kernel_syms               130
+#define TARGET_NR_quotactl                      131
+#define TARGET_NR_getpgid                       132
+#define TARGET_NR_fchdir                        133
+#define TARGET_NR_bdflush                       134
+#define TARGET_NR_sysfs                         135
+#define TARGET_NR_personality                   136
+#define TARGET_NR_afs_syscall                   137
+#define TARGET_NR_setfsuid                      138
+#define TARGET_NR_setfsgid                      139
+#define TARGET_NR__llseek                       140
+#define TARGET_NR_getdents                      141
+#define TARGET_NR__newselect                    142
+#define TARGET_NR_flock                         143
+#define TARGET_NR_msync                         144
+#define TARGET_NR_readv                         145
+#define TARGET_NR_writev                        146
+#define TARGET_NR_getsid                        147
+#define TARGET_NR_fdatasync                     148
+#define TARGET_NR__sysctl                       149
+#define TARGET_NR_mlock                         150
+#define TARGET_NR_munlock                       151
+#define TARGET_NR_mlockall                      152
+#define TARGET_NR_munlockall                    153
+#define TARGET_NR_sched_setparam                154
+#define TARGET_NR_sched_getparam                155
+#define TARGET_NR_sched_setscheduler            156
+#define TARGET_NR_sched_getscheduler            157
+#define TARGET_NR_sched_yield                   158
+#define TARGET_NR_sched_get_priority_max        159
+#define TARGET_NR_sched_get_priority_min        160
+#define TARGET_NR_sched_rr_get_interval         161
+#define TARGET_NR_nanosleep                     162
+#define TARGET_NR_mremap                        163
+#define TARGET_NR_setresuid                     164
+#define TARGET_NR_getresuid                     165
+#define TARGET_NR_vm86                          166
+#define TARGET_NR_query_module                  167
+#define TARGET_NR_poll                          168
+#define TARGET_NR_nfsservctl                    169
+#define TARGET_NR_setresgid                     170
+#define TARGET_NR_getresgid                     171
+#define TARGET_NR_prctl                         172
+#define TARGET_NR_rt_sigreturn                  173
+#define TARGET_NR_rt_sigaction                  174
+#define TARGET_NR_rt_sigprocmask                175
+#define TARGET_NR_rt_sigpending                 176
+#define TARGET_NR_rt_sigtimedwait               177
+#define TARGET_NR_rt_sigqueueinfo               178
+#define TARGET_NR_rt_sigsuspend                 179
+#define TARGET_NR_pread                         180
+#define TARGET_NR_pwrite                        181
+#define TARGET_NR_chown                         182
+#define TARGET_NR_getcwd                        183
+#define TARGET_NR_capget                        184
+#define TARGET_NR_capset                        185
+#define TARGET_NR_sigaltstack                   186
+#define TARGET_NR_sendfile                      187
+                                                /* 188 */
+                                                /* 189 */
+#define TARGET_NR_vfork                         190
+#define TARGET_NR_ugetrlimit                    191
+#define TARGET_NR_mmap2                         192
+#define TARGET_NR_truncate64                    193
+#define TARGET_NR_ftruncate64                   194
+#define TARGET_NR_stat64                        195
+#define TARGET_NR_lstat64                       196
+#define TARGET_NR_fstat64                       197
+#define TARGET_NR_lchown32                      198
+#define TARGET_NR_getuid32                      199
+#define TARGET_NR_getgid32                      200
+#define TARGET_NR_geteuid32                     201
+#define TARGET_NR_getegid32                     202
+#define TARGET_NR_setreuid32                    203
+#define TARGET_NR_setregid32                    204
+#define TARGET_NR_getgroups32                   205
+#define TARGET_NR_setgroups32                   206
+#define TARGET_NR_fchown32                      207
+#define TARGET_NR_setresuid32                   208
+#define TARGET_NR_getresuid32                   209
+#define TARGET_NR_setresgid32                   210
+#define TARGET_NR_getresgid32                   211
+#define TARGET_NR_chown32                       212
+#define TARGET_NR_setuid32                      213
+#define TARGET_NR_setgid32                      214
+#define TARGET_NR_setfsuid32                    215
+#define TARGET_NR_setfsgid32                    216
+#define TARGET_NR_getdents64                    217
+#define TARGET_NR_pivot_root                    218
+#define TARGET_NR_mincore                       219
+#define TARGET_NR_madvise                       220
+#define TARGET_NR_fcntl64                       221
+                                                /* 222 */
+                                                /* 223 */
+#define TARGET_NR_gettid                        224
+#define TARGET_NR_readahead                     225
+#define TARGET_NR_setxattr                      226
+#define TARGET_NR_lsetxattr                     227
+#define TARGET_NR_fsetxattr                     228
+#define TARGET_NR_getxattr                      229
+#define TARGET_NR_lgetxattr                     230
+#define TARGET_NR_fgetxattr                     231
+#define TARGET_NR_listxattr                     232
+#define TARGET_NR_llistxattr                    233
+#define TARGET_NR_flistxattr                    234
+#define TARGET_NR_removexattr                   235
+#define TARGET_NR_lremovexattr                  236
+#define TARGET_NR_fremovexattr                  237
+#define TARGET_NR_tkill                         238
+#define TARGET_NR_sendfile64                    239
+#define TARGET_NR_futex                         240
+#define TARGET_NR_sched_setaffinity             241
+#define TARGET_NR_sched_getaffinity             242
+#define TARGET_NR_io_setup                      243
+#define TARGET_NR_io_destroy                    244
+#define TARGET_NR_io_getevents                  245
+#define TARGET_NR_io_submit                     246
+#define TARGET_NR_io_cancel                     247
+#define TARGET_NR_exit_group                    248
+#define TARGET_NR_lookup_dcookie                249
+#define TARGET_NR_epoll_create                  250
+#define TARGET_NR_epoll_ctl                     251
+#define TARGET_NR_epoll_wait                    252
+#define TARGET_NR_remap_file_pages              253
+                                                /* 254 */
+                                                /* 255 */
+                                                /* 256 */
+#define TARGET_NR_set_tid_address               256
+#define TARGET_NR_timer_create                  257
+#define TARGET_NR_timer_settime                 258
+#define TARGET_NR_timer_gettime                 259
+#define TARGET_NR_timer_getoverrun              260
+#define TARGET_NR_timer_delete                  261
+#define TARGET_NR_clock_settime                 262
+#define TARGET_NR_clock_gettime                 263
+#define TARGET_NR_clock_getres                  264
+#define TARGET_NR_clock_nanosleep               265
+#define TARGET_NR_statfs64                      266
+#define TARGET_NR_fstatfs64                     267
+#define TARGET_NR_tgkill                        268
+#define TARGET_NR_utimes                        269
+#define TARGET_NR_fadvise64_64                  270
+#define TARGET_NR_pciconfig_iobase              271
+#define TARGET_NR_pciconfig_read                272
+#define TARGET_NR_pciconfig_write               273
+#define TARGET_NR_mq_open                       274
+#define TARGET_NR_mq_unlink                     275
+#define TARGET_NR_mq_timedsend                  276
+#define TARGET_NR_mq_timedreceive               277
+#define TARGET_NR_mq_notify                     278
+#define TARGET_NR_mq_getsetattr                 279
+#define TARGET_NR_waitid                        280
+#define TARGET_NR_socket                        281
+#define TARGET_NR_bind                          282
+#define TARGET_NR_connect                       283
+#define TARGET_NR_listen                        284
+#define TARGET_NR_accept                        285
+#define TARGET_NR_getsockname                   286
+#define TARGET_NR_getpeername                   287
+#define TARGET_NR_socketpair                    288
+#define TARGET_NR_send                          289
+#define TARGET_NR_sendto                        290
+#define TARGET_NR_recv                          291
+#define TARGET_NR_recvfrom                      292
+#define TARGET_NR_shutdown                      293
+#define TARGET_NR_setsockopt                    294
+#define TARGET_NR_getsockopt                    295
+#define TARGET_NR_sendmsg                       296
+#define TARGET_NR_recvmsg                       297
+#define TARGET_NR_semop                         298
+#define TARGET_NR_semget                        299
+#define TARGET_NR_semctl                        300
+#define TARGET_NR_msgsnd                        301
+#define TARGET_NR_msgrcv                        302
+#define TARGET_NR_msgget                        303
+#define TARGET_NR_msgctl                        304
+#define TARGET_NR_shmat                         305
+#define TARGET_NR_shmdt                         306
+#define TARGET_NR_shmget                        307
+#define TARGET_NR_shmctl                        308
+#define TARGET_NR_add_key                       309
+#define TARGET_NR_request_key                   310
+#define TARGET_NR_keyctl                        311
+#define TARGET_NR_semtimedop                    312
+#define TARGET_NR_vserver                       313
+#define TARGET_NR_ioprio_set                    314
+#define TARGET_NR_ioprio_get                    315
+#define TARGET_NR_inotify_init                  316
+#define TARGET_NR_inotify_add_watch             317
+#define TARGET_NR_inotify_rm_watch              318
+#define TARGET_NR_mbind                         319
+#define TARGET_NR_get_mempolicy                 320
+#define TARGET_NR_set_mempolicy                 321
+#define TARGET_NR_openat                        322
+#define TARGET_NR_mkdirat                       323
+#define TARGET_NR_mknodat                       324
+#define TARGET_NR_fchownat                      325
+#define TARGET_NR_futimesat                     326
+#define TARGET_NR_fstatat64                     327
+#define TARGET_NR_unlinkat                      328
+#define TARGET_NR_renameat                      329
+#define TARGET_NR_linkat                        330
+#define TARGET_NR_symlinkat                     331
+#define TARGET_NR_readlinkat                    332
+#define TARGET_NR_fchmodat                      333
+#define TARGET_NR_faccessat                     334
+                                                /* 335 */
+                                                /* 336 */
+#define TARGET_NR_unshare                       337
+#define TARGET_NR_set_robust_list               338
+#define TARGET_NR_get_robust_list               339
+#define TARGET_NR_splice                        340
+#define TARGET_NR_sync_file_range2              341
+#define TARGET_NR_tee                           342
+#define TARGET_NR_vmsplice                      343
+#define TARGET_NR_move_pages                    344
+#define TARGET_NR_getcpu                        345
+                                                /* 346 */
+#define TARGET_NR_kexec_load                    347
+#define TARGET_NR_utimensat                     348
+#define TARGET_NR_signalfd                      349
+#define TARGET_NR_timerfd                       350
+#define TARGET_NR_eventfd                       351
+#define TARGET_NR_fallocate                     352
+#define TARGET_NR_timerfd_settime               353
+#define TARGET_NR_timerfd_gettime               354
+#define TARGET_NR_signalfd4                     355
+#define TARGET_NR_eventfd2                      356
+#define TARGET_NR_epoll_create1                 357
+#define TARGET_NR_dup3                          358
+#define TARGET_NR_pipe2                         359
+#define TARGET_NR_inotify_init1                 360
diff --git a/linux-user/unicore32/target_signal.h b/linux-user/unicore32/target_signal.h
new file mode 100644
index 0000000..8b255c4
--- /dev/null
+++ b/linux-user/unicore32/target_signal.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+    abi_ulong ss_sp;
+    abi_ulong ss_flags;
+    abi_ulong ss_size;
+} target_stack_t;
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK               1
+#define TARGET_SS_DISABLE               2
+
+#define get_sp_from_cpustate(cpustate)  (cpustate->regs[29])
+
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/unicore32/termbits.h b/linux-user/unicore32/termbits.h
new file mode 100644
index 0000000..a5fcd64
--- /dev/null
+++ b/linux-user/unicore32/termbits.h
@@ -0,0 +1,2 @@
+/* NOTE: exactly the same as i386 */
+#include "../i386/termbits.h"
commit 6e64da3cd6890181fbeaaae7c08cfb779f138d82
Author: Guan Xuetao <gxt at mprc.pku.edu.cn>
Date:   Tue Apr 12 16:25:59 2011 +0800

    unicore32: add target-unicore32 directory for unicore32-linux-user support
    
    Signed-off-by: Guan Xuetao <gxt at mprc.pku.edu.cn>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
new file mode 100644
index 0000000..1e10049
--- /dev/null
+++ b/target-unicore32/cpu.h
@@ -0,0 +1,182 @@
+/*
+ * UniCore32 virtual CPU header
+ *
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __CPU_UC32_H__
+#define __CPU_UC32_H__
+
+#define TARGET_LONG_BITS                32
+#define TARGET_PAGE_BITS                12
+
+#define TARGET_PHYS_ADDR_SPACE_BITS     32
+#define TARGET_VIRT_ADDR_SPACE_BITS     32
+
+#define ELF_MACHINE             EM_UNICORE32
+
+#define CPUState                struct CPUState_UniCore32
+
+#include "cpu-defs.h"
+#include "softfloat.h"
+
+#define NB_MMU_MODES            2
+
+typedef struct CPUState_UniCore32 {
+    /* Regs for current mode.  */
+    uint32_t regs[32];
+    /* Frequently accessed ASR bits are stored separately for efficiently.
+       This contains all the other bits.  Use asr_{read,write} to access
+       the whole ASR.  */
+    uint32_t uncached_asr;
+    uint32_t bsr;
+
+    /* Banked registers.  */
+    uint32_t banked_bsr[6];
+    uint32_t banked_r29[6];
+    uint32_t banked_r30[6];
+
+    /* asr flag cache for faster execution */
+    uint32_t CF; /* 0 or 1 */
+    uint32_t VF; /* V is the bit 31. All other bits are undefined */
+    uint32_t NF; /* N is bit 31. All other bits are undefined.  */
+    uint32_t ZF; /* Z set if zero.  */
+
+    /* System control coprocessor (cp0) */
+    struct {
+        uint32_t c0_cpuid;
+        uint32_t c0_cachetype;
+        uint32_t c1_sys; /* System control register.  */
+        uint32_t c2_base; /* MMU translation table base.  */
+        uint32_t c3_faultstatus; /* Fault status registers.  */
+        uint32_t c4_faultaddr; /* Fault address registers.  */
+        uint32_t c5_cacheop; /* Cache operation registers.  */
+        uint32_t c6_tlbop; /* TLB operation registers. */
+    } cp0;
+
+    /* UniCore-F64 coprocessor state.  */
+    struct {
+        float64 regs[16];
+        uint32_t xregs[32];
+        float_status fp_status;
+    } ucf64;
+
+    CPU_COMMON
+
+    /* Internal CPU feature flags.  */
+    uint32_t features;
+
+} CPUState_UniCore32;
+
+#define ASR_M                   (0x1f)
+#define ASR_MODE_USER           (0x10)
+#define ASR_MODE_INTR           (0x12)
+#define ASR_MODE_PRIV           (0x13)
+#define ASR_MODE_TRAP           (0x17)
+#define ASR_MODE_EXTN           (0x1b)
+#define ASR_MODE_SUSR           (0x1f)
+#define ASR_I                   (1 << 7)
+#define ASR_V                   (1 << 28)
+#define ASR_C                   (1 << 29)
+#define ASR_Z                   (1 << 30)
+#define ASR_N                   (1 << 31)
+#define ASR_NZCV                (ASR_N | ASR_Z | ASR_C | ASR_V)
+#define ASR_RESERVED            (~(ASR_M | ASR_I | ASR_NZCV))
+
+#define UC32_EXCP_PRIV          (ASR_MODE_PRIV)
+#define UC32_EXCP_TRAP          (ASR_MODE_TRAP)
+
+/* Return the current ASR value.  */
+target_ulong cpu_asr_read(CPUState *env1);
+/* Set the ASR.  Note that some bits of mask must be all-set or all-clear.  */
+void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask);
+
+/* UniCore-F64 system registers.  */
+#define UC32_UCF64_FPSCR                (31)
+#define UCF64_FPSCR_MASK                (0x27ffffff)
+#define UCF64_FPSCR_RND_MASK            (0x7)
+#define UCF64_FPSCR_RND(r)              (((r) >>  0) & UCF64_FPSCR_RND_MASK)
+#define UCF64_FPSCR_TRAPEN_MASK         (0x7f)
+#define UCF64_FPSCR_TRAPEN(r)           (((r) >> 10) & UCF64_FPSCR_TRAPEN_MASK)
+#define UCF64_FPSCR_FLAG_MASK           (0x3ff)
+#define UCF64_FPSCR_FLAG(r)             (((r) >> 17) & UCF64_FPSCR_FLAG_MASK)
+#define UCF64_FPSCR_FLAG_ZERO           (1 << 17)
+#define UCF64_FPSCR_FLAG_INFINITY       (1 << 18)
+#define UCF64_FPSCR_FLAG_INVALID        (1 << 19)
+#define UCF64_FPSCR_FLAG_UNDERFLOW      (1 << 20)
+#define UCF64_FPSCR_FLAG_OVERFLOW       (1 << 21)
+#define UCF64_FPSCR_FLAG_INEXACT        (1 << 22)
+#define UCF64_FPSCR_FLAG_HUGEINT        (1 << 23)
+#define UCF64_FPSCR_FLAG_DENORMAL       (1 << 24)
+#define UCF64_FPSCR_FLAG_UNIMP          (1 << 25)
+#define UCF64_FPSCR_FLAG_DIVZERO        (1 << 26)
+
+#define UC32_HWCAP_CMOV                 4 /* 1 << 2 */
+#define UC32_HWCAP_UCF64                8 /* 1 << 3 */
+
+#define UC32_CPUID(env)                 (env->cp0.c0_cpuid)
+#define UC32_CPUID_UCV2                 0x40010863
+#define UC32_CPUID_ANY                  0xffffffff
+
+#define cpu_init                        uc32_cpu_init
+#define cpu_exec                        uc32_cpu_exec
+#define cpu_signal_handler              uc32_cpu_signal_handler
+#define cpu_handle_mmu_fault            uc32_cpu_handle_mmu_fault
+
+CPUState *uc32_cpu_init(const char *cpu_model);
+int uc32_cpu_exec(CPUState *s);
+int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
+int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+                              int mmu_idx, int is_softmuu);
+
+#define CPU_SAVE_VERSION 2
+
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+static inline int cpu_mmu_index(CPUState *env)
+{
+    return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0;
+}
+
+static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[29] = newsp;
+    }
+    env->regs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+    env->regs[16] = newtls;
+}
+
+#include "cpu-all.h"
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+    env->regs[31] = tb->pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->regs[31];
+    *cs_base = 0;
+    *flags = 0;
+    if ((env->uncached_asr & ASR_M) != ASR_MODE_USER) {
+        *flags |= (1 << 6);
+    }
+}
+
+void uc32_translate_init(void);
+void do_interrupt(CPUState *);
+void switch_mode(CPUState_UniCore32 *, int);
+
+#endif /* __CPU_UC32_H__ */
diff --git a/target-unicore32/exec.h b/target-unicore32/exec.h
new file mode 100644
index 0000000..4ab55f4
--- /dev/null
+++ b/target-unicore32/exec.h
@@ -0,0 +1,50 @@
+/*
+ *  UniCore32 execution defines
+ *
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __UC32_EXEC_H__
+#define __UC32_EXEC_H__
+
+#include "config.h"
+#include "dyngen-exec.h"
+
+register struct CPUState_UniCore32 *env asm(AREG0);
+
+#include "cpu.h"
+#include "exec-all.h"
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+static inline int cpu_has_work(CPUState *env)
+{
+    return env->interrupt_request &
+        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+}
+
+static inline int cpu_halted(CPUState *env)
+{
+    if (!env->halted) {
+        return 0;
+    }
+    /* An interrupt wakes the CPU even if the I and R ASR bits are
+       set.  We use EXITTB to silently wake CPU without causing an
+       actual interrupt.  */
+    if (cpu_has_work(env)) {
+        env->halted = 0;
+        return 0;
+    }
+    return EXCP_HALTED;
+}
+
+#endif /* __UC32_EXEC_H__ */
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
new file mode 100644
index 0000000..483aeae
--- /dev/null
+++ b/target-unicore32/helper.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "helper.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+
+static inline void set_feature(CPUState *env, int feature)
+{
+    env->features |= feature;
+}
+
+struct uc32_cpu_t {
+    uint32_t id;
+    const char *name;
+};
+
+static const struct uc32_cpu_t uc32_cpu_names[] = {
+    { UC32_CPUID_UCV2, "UniCore-II"},
+    { UC32_CPUID_ANY, "any"},
+    { 0, NULL}
+};
+
+/* return 0 if not found */
+static uint32_t uc32_cpu_find_by_name(const char *name)
+{
+    int i;
+    uint32_t id;
+
+    id = 0;
+    for (i = 0; uc32_cpu_names[i].name; i++) {
+        if (strcmp(name, uc32_cpu_names[i].name) == 0) {
+            id = uc32_cpu_names[i].id;
+            break;
+        }
+    }
+    return id;
+}
+
+CPUState *uc32_cpu_init(const char *cpu_model)
+{
+    CPUState *env;
+    uint32_t id;
+    static int inited = 1;
+
+    env = qemu_mallocz(sizeof(CPUState));
+    cpu_exec_init(env);
+
+    id = uc32_cpu_find_by_name(cpu_model);
+    switch (id) {
+    case UC32_CPUID_UCV2:
+        set_feature(env, UC32_HWCAP_CMOV);
+        set_feature(env, UC32_HWCAP_UCF64);
+        env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
+        env->cp0.c0_cachetype = 0x1dd20d2;
+        env->cp0.c1_sys = 0x00090078;
+        break;
+    case UC32_CPUID_ANY: /* For userspace emulation.  */
+        set_feature(env, UC32_HWCAP_CMOV);
+        set_feature(env, UC32_HWCAP_UCF64);
+        break;
+    default:
+        cpu_abort(env, "Bad CPU ID: %x\n", id);
+    }
+
+    env->cpu_model_str = cpu_model;
+    env->cp0.c0_cpuid = id;
+    env->uncached_asr = ASR_MODE_USER;
+    env->regs[31] = 0;
+
+    if (inited) {
+        inited = 0;
+        uc32_translate_init();
+    }
+
+    tlb_flush(env, 1);
+    qemu_init_vcpu(env);
+    return env;
+}
+
+uint32_t HELPER(clo)(uint32_t x)
+{
+    return clo32(x);
+}
+
+uint32_t HELPER(clz)(uint32_t x)
+{
+    return clz32(x);
+}
+
+void do_interrupt(CPUState *env)
+{
+    env->exception_index = -1;
+}
+
+int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+                              int mmu_idx, int is_softmmu)
+{
+    env->exception_index = UC32_EXCP_TRAP;
+    env->cp0.c4_faultaddr = address;
+    return 1;
+}
+
+/* These should probably raise undefined insn exceptions.  */
+void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
+{
+    int op1 = (insn >> 8) & 0xf;
+    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
+    return;
+}
+
+uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
+{
+    int op1 = (insn >> 8) & 0xf;
+    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
+    return 0;
+}
+
+void HELPER(set_cp0)(CPUState *env, uint32_t insn, uint32_t val)
+{
+    cpu_abort(env, "cp0 insn %08x\n", insn);
+}
+
+uint32_t HELPER(get_cp0)(CPUState *env, uint32_t insn)
+{
+    cpu_abort(env, "cp0 insn %08x\n", insn);
+    return 0;
+}
+
+void switch_mode(CPUState *env, int mode)
+{
+    if (mode != ASR_MODE_USER) {
+        cpu_abort(env, "Tried to switch out of user mode\n");
+    }
+}
+
+void HELPER(set_r29_banked)(CPUState *env, uint32_t mode, uint32_t val)
+{
+    cpu_abort(env, "banked r29 write\n");
+}
+
+uint32_t HELPER(get_r29_banked)(CPUState *env, uint32_t mode)
+{
+    cpu_abort(env, "banked r29 read\n");
+    return 0;
+}
+
+/* UniCore-F64 support.  We follow the convention used for F64 instrunctions:
+   Single precition routines have a "s" suffix, double precision a
+   "d" suffix.  */
+
+/* Convert host exception flags to f64 form.  */
+static inline int ucf64_exceptbits_from_host(int host_bits)
+{
+    int target_bits = 0;
+
+    if (host_bits & float_flag_invalid) {
+        target_bits |= UCF64_FPSCR_FLAG_INVALID;
+    }
+    if (host_bits & float_flag_divbyzero) {
+        target_bits |= UCF64_FPSCR_FLAG_DIVZERO;
+    }
+    if (host_bits & float_flag_overflow) {
+        target_bits |= UCF64_FPSCR_FLAG_OVERFLOW;
+    }
+    if (host_bits & float_flag_underflow) {
+        target_bits |= UCF64_FPSCR_FLAG_UNDERFLOW;
+    }
+    if (host_bits & float_flag_inexact) {
+        target_bits |= UCF64_FPSCR_FLAG_INEXACT;
+    }
+    return target_bits;
+}
+
+uint32_t HELPER(ucf64_get_fpscr)(CPUState *env)
+{
+    int i;
+    uint32_t fpscr;
+
+    fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK);
+    i = get_float_exception_flags(&env->ucf64.fp_status);
+    fpscr |= ucf64_exceptbits_from_host(i);
+    return fpscr;
+}
+
+/* Convert ucf64 exception flags to target form.  */
+static inline int ucf64_exceptbits_to_host(int target_bits)
+{
+    int host_bits = 0;
+
+    if (target_bits & UCF64_FPSCR_FLAG_INVALID) {
+        host_bits |= float_flag_invalid;
+    }
+    if (target_bits & UCF64_FPSCR_FLAG_DIVZERO) {
+        host_bits |= float_flag_divbyzero;
+    }
+    if (target_bits & UCF64_FPSCR_FLAG_OVERFLOW) {
+        host_bits |= float_flag_overflow;
+    }
+    if (target_bits & UCF64_FPSCR_FLAG_UNDERFLOW) {
+        host_bits |= float_flag_underflow;
+    }
+    if (target_bits & UCF64_FPSCR_FLAG_INEXACT) {
+        host_bits |= float_flag_inexact;
+    }
+    return host_bits;
+}
+
+void HELPER(ucf64_set_fpscr)(CPUState *env, uint32_t val)
+{
+    int i;
+    uint32_t changed;
+
+    changed = env->ucf64.xregs[UC32_UCF64_FPSCR];
+    env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK);
+
+    changed ^= val;
+    if (changed & (UCF64_FPSCR_RND_MASK)) {
+        i = UCF64_FPSCR_RND(val);
+        switch (i) {
+        case 0:
+            i = float_round_nearest_even;
+            break;
+        case 1:
+            i = float_round_to_zero;
+            break;
+        case 2:
+            i = float_round_up;
+            break;
+        case 3:
+            i = float_round_down;
+            break;
+        default: /* 100 and 101 not implement */
+            cpu_abort(env, "Unsupported UniCore-F64 round mode");
+        }
+        set_float_rounding_mode(i, &env->ucf64.fp_status);
+    }
+
+    i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val));
+    set_float_exception_flags(i, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUState *env)
+{
+    return float32_add(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUState *env)
+{
+    return float64_add(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUState *env)
+{
+    return float32_sub(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUState *env)
+{
+    return float64_sub(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUState *env)
+{
+    return float32_mul(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUState *env)
+{
+    return float64_mul(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUState *env)
+{
+    return float32_div(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUState *env)
+{
+    return float64_div(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_negs)(float32 a)
+{
+    return float32_chs(a);
+}
+
+float64 HELPER(ucf64_negd)(float64 a)
+{
+    return float64_chs(a);
+}
+
+float32 HELPER(ucf64_abss)(float32 a)
+{
+    return float32_abs(a);
+}
+
+float64 HELPER(ucf64_absd)(float64 a)
+{
+    return float64_abs(a);
+}
+
+/* XXX: check quiet/signaling case */
+void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, CPUState *env)
+{
+    int flag;
+    flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
+    env->CF = 0;
+    switch (c & 0x7) {
+    case 0: /* F */
+        break;
+    case 1: /* UN */
+        if (flag == 2) {
+            env->CF = 1;
+        }
+        break;
+    case 2: /* EQ */
+        if (flag == 0) {
+            env->CF = 1;
+        }
+        break;
+    case 3: /* UEQ */
+        if ((flag == 0) || (flag == 2)) {
+            env->CF = 1;
+        }
+        break;
+    case 4: /* OLT */
+        if (flag == -1) {
+            env->CF = 1;
+        }
+        break;
+    case 5: /* ULT */
+        if ((flag == -1) || (flag == 2)) {
+            env->CF = 1;
+        }
+        break;
+    case 6: /* OLE */
+        if ((flag == -1) || (flag == 0)) {
+            env->CF = 1;
+        }
+        break;
+    case 7: /* ULE */
+        if (flag != 1) {
+            env->CF = 1;
+        }
+        break;
+    }
+    env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
+                    | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
+}
+
+void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, CPUState *env)
+{
+    int flag;
+    flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
+    env->CF = 0;
+    switch (c & 0x7) {
+    case 0: /* F */
+        break;
+    case 1: /* UN */
+        if (flag == 2) {
+            env->CF = 1;
+        }
+        break;
+    case 2: /* EQ */
+        if (flag == 0) {
+            env->CF = 1;
+        }
+        break;
+    case 3: /* UEQ */
+        if ((flag == 0) || (flag == 2)) {
+            env->CF = 1;
+        }
+        break;
+    case 4: /* OLT */
+        if (flag == -1) {
+            env->CF = 1;
+        }
+        break;
+    case 5: /* ULT */
+        if ((flag == -1) || (flag == 2)) {
+            env->CF = 1;
+        }
+        break;
+    case 6: /* OLE */
+        if ((flag == -1) || (flag == 0)) {
+            env->CF = 1;
+        }
+        break;
+    case 7: /* ULE */
+        if (flag != 1) {
+            env->CF = 1;
+        }
+        break;
+    }
+    env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
+                    | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
+}
+
+/* Helper routines to perform bitwise copies between float and int.  */
+static inline float32 ucf64_itos(uint32_t i)
+{
+    union {
+        uint32_t i;
+        float32 s;
+    } v;
+
+    v.i = i;
+    return v.s;
+}
+
+static inline uint32_t ucf64_stoi(float32 s)
+{
+    union {
+        uint32_t i;
+        float32 s;
+    } v;
+
+    v.s = s;
+    return v.i;
+}
+
+static inline float64 ucf64_itod(uint64_t i)
+{
+    union {
+        uint64_t i;
+        float64 d;
+    } v;
+
+    v.i = i;
+    return v.d;
+}
+
+static inline uint64_t ucf64_dtoi(float64 d)
+{
+    union {
+        uint64_t i;
+        float64 d;
+    } v;
+
+    v.d = d;
+    return v.i;
+}
+
+/* Integer to float conversion.  */
+float32 HELPER(ucf64_si2sf)(float32 x, CPUState *env)
+{
+    return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_si2df)(float32 x, CPUState *env)
+{
+    return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
+}
+
+/* Float to integer conversion.  */
+float32 HELPER(ucf64_sf2si)(float32 x, CPUState *env)
+{
+    return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
+}
+
+float32 HELPER(ucf64_df2si)(float64 x, CPUState *env)
+{
+    return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
+}
+
+/* floating point conversion */
+float64 HELPER(ucf64_sf2df)(float32 x, CPUState *env)
+{
+    return float32_to_float64(x, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_df2sf)(float64 x, CPUState *env)
+{
+    return float64_to_float32(x, &env->ucf64.fp_status);
+}
diff --git a/target-unicore32/helper.h b/target-unicore32/helper.h
new file mode 100644
index 0000000..615de2a
--- /dev/null
+++ b/target-unicore32/helper.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "def-helper.h"
+
+DEF_HELPER_1(clz, i32, i32)
+DEF_HELPER_1(clo, i32, i32)
+
+DEF_HELPER_1(exception, void, i32)
+
+DEF_HELPER_2(asr_write, void, i32, i32)
+DEF_HELPER_0(asr_read, i32)
+
+DEF_HELPER_3(set_cp0, void, env, i32, i32)
+DEF_HELPER_2(get_cp0, i32, env, i32)
+
+DEF_HELPER_3(set_cp, void, env, i32, i32)
+DEF_HELPER_2(get_cp, i32, env, i32)
+
+DEF_HELPER_1(get_user_reg, i32, i32)
+DEF_HELPER_2(set_user_reg, void, i32, i32)
+
+DEF_HELPER_2(add_cc, i32, i32, i32)
+DEF_HELPER_2(adc_cc, i32, i32, i32)
+DEF_HELPER_2(sub_cc, i32, i32, i32)
+DEF_HELPER_2(sbc_cc, i32, i32, i32)
+
+DEF_HELPER_2(shl, i32, i32, i32)
+DEF_HELPER_2(shr, i32, i32, i32)
+DEF_HELPER_2(sar, i32, i32, i32)
+DEF_HELPER_2(shl_cc, i32, i32, i32)
+DEF_HELPER_2(shr_cc, i32, i32, i32)
+DEF_HELPER_2(sar_cc, i32, i32, i32)
+DEF_HELPER_2(ror_cc, i32, i32, i32)
+
+DEF_HELPER_2(get_r29_banked, i32, env, i32)
+DEF_HELPER_3(set_r29_banked, void, env, i32, i32)
+
+DEF_HELPER_1(ucf64_get_fpscr, i32, env)
+DEF_HELPER_2(ucf64_set_fpscr, void, env, i32)
+
+DEF_HELPER_3(ucf64_adds, f32, f32, f32, env)
+DEF_HELPER_3(ucf64_addd, f64, f64, f64, env)
+DEF_HELPER_3(ucf64_subs, f32, f32, f32, env)
+DEF_HELPER_3(ucf64_subd, f64, f64, f64, env)
+DEF_HELPER_3(ucf64_muls, f32, f32, f32, env)
+DEF_HELPER_3(ucf64_muld, f64, f64, f64, env)
+DEF_HELPER_3(ucf64_divs, f32, f32, f32, env)
+DEF_HELPER_3(ucf64_divd, f64, f64, f64, env)
+DEF_HELPER_1(ucf64_negs, f32, f32)
+DEF_HELPER_1(ucf64_negd, f64, f64)
+DEF_HELPER_1(ucf64_abss, f32, f32)
+DEF_HELPER_1(ucf64_absd, f64, f64)
+DEF_HELPER_4(ucf64_cmps, void, f32, f32, i32, env)
+DEF_HELPER_4(ucf64_cmpd, void, f64, f64, i32, env)
+
+DEF_HELPER_2(ucf64_sf2df, f64, f32, env)
+DEF_HELPER_2(ucf64_df2sf, f32, f64, env)
+
+DEF_HELPER_2(ucf64_si2sf, f32, f32, env)
+DEF_HELPER_2(ucf64_si2df, f64, f32, env)
+
+DEF_HELPER_2(ucf64_sf2si, f32, f32, env)
+DEF_HELPER_2(ucf64_df2si, f32, f64, env)
+
+#include "def-helper.h"
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
new file mode 100644
index 0000000..31e4b11
--- /dev/null
+++ b/target-unicore32/op_helper.c
@@ -0,0 +1,248 @@
+/*
+ *  UniCore32 helper routines
+ *
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "exec.h"
+#include "helper.h"
+
+#define SIGNBIT (uint32_t)0x80000000
+#define SIGNBIT64 ((uint64_t)1 << 63)
+
+void HELPER(exception)(uint32_t excp)
+{
+    env->exception_index = excp;
+    cpu_loop_exit();
+}
+
+static target_ulong asr_read(void)
+{
+    int ZF;
+    ZF = (env->ZF == 0);
+    return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
+        (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
+}
+
+target_ulong cpu_asr_read(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = asr_read();
+    env = saved_env;
+    return ret;
+}
+
+target_ulong HELPER(asr_read)(void)
+{
+    return asr_read();
+}
+
+static void asr_write(target_ulong val, target_ulong mask)
+{
+    if (mask & ASR_NZCV) {
+        env->ZF = (~val) & ASR_Z;
+        env->NF = val;
+        env->CF = (val >> 29) & 1;
+        env->VF = (val << 3) & 0x80000000;
+    }
+
+    if ((env->uncached_asr ^ val) & mask & ASR_M) {
+        switch_mode(env, val & ASR_M);
+    }
+    mask &= ~ASR_NZCV;
+    env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
+}
+
+void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    asr_write(val, mask);
+    env = saved_env;
+}
+
+void HELPER(asr_write)(target_ulong val, target_ulong mask)
+{
+    asr_write(val, mask);
+}
+
+/* Access to user mode registers from privileged modes.  */
+uint32_t HELPER(get_user_reg)(uint32_t regno)
+{
+    uint32_t val;
+
+    if (regno == 29) {
+        val = env->banked_r29[0];
+    } else if (regno == 30) {
+        val = env->banked_r30[0];
+    } else {
+        val = env->regs[regno];
+    }
+    return val;
+}
+
+void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
+{
+    if (regno == 29) {
+        env->banked_r29[0] = val;
+    } else if (regno == 30) {
+        env->banked_r30[0] = val;
+    } else {
+        env->regs[regno] = val;
+    }
+}
+
+/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
+   The only way to do that in TCG is a conditional branch, which clobbers
+   all our temporaries.  For now implement these as helper functions.  */
+
+uint32_t HELPER(add_cc)(uint32_t a, uint32_t b)
+{
+    uint32_t result;
+    result = a + b;
+    env->NF = env->ZF = result;
+    env->CF = result < a;
+    env->VF = (a ^ b ^ -1) & (a ^ result);
+    return result;
+}
+
+uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
+{
+    uint32_t result;
+    if (!env->CF) {
+        result = a + b;
+        env->CF = result < a;
+    } else {
+        result = a + b + 1;
+        env->CF = result <= a;
+    }
+    env->VF = (a ^ b ^ -1) & (a ^ result);
+    env->NF = env->ZF = result;
+    return result;
+}
+
+uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
+{
+    uint32_t result;
+    result = a - b;
+    env->NF = env->ZF = result;
+    env->CF = a >= b;
+    env->VF = (a ^ b) & (a ^ result);
+    return result;
+}
+
+uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
+{
+    uint32_t result;
+    if (!env->CF) {
+        result = a - b - 1;
+        env->CF = a > b;
+    } else {
+        result = a - b;
+        env->CF = a >= b;
+    }
+    env->VF = (a ^ b) & (a ^ result);
+    env->NF = env->ZF = result;
+    return result;
+}
+
+/* Similarly for variable shift instructions.  */
+
+uint32_t HELPER(shl)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        return 0;
+    }
+    return x << shift;
+}
+
+uint32_t HELPER(shr)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        return 0;
+    }
+    return (uint32_t)x >> shift;
+}
+
+uint32_t HELPER(sar)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        shift = 31;
+    }
+    return (int32_t)x >> shift;
+}
+
+uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        if (shift == 32) {
+            env->CF = x & 1;
+        } else {
+            env->CF = 0;
+        }
+        return 0;
+    } else if (shift != 0) {
+        env->CF = (x >> (32 - shift)) & 1;
+        return x << shift;
+    }
+    return x;
+}
+
+uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        if (shift == 32) {
+            env->CF = (x >> 31) & 1;
+        } else {
+            env->CF = 0;
+        }
+        return 0;
+    } else if (shift != 0) {
+        env->CF = (x >> (shift - 1)) & 1;
+        return x >> shift;
+    }
+    return x;
+}
+
+uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
+{
+    int shift = i & 0xff;
+    if (shift >= 32) {
+        env->CF = (x >> 31) & 1;
+        return (int32_t)x >> 31;
+    } else if (shift != 0) {
+        env->CF = (x >> (shift - 1)) & 1;
+        return (int32_t)x >> shift;
+    }
+    return x;
+}
+
+uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
+{
+    int shift1, shift;
+    shift1 = i & 0xff;
+    shift = shift1 & 0x1f;
+    if (shift == 0) {
+        if (shift1 != 0) {
+            env->CF = (x >> 31) & 1;
+        }
+        return x;
+    } else {
+        env->CF = (x >> (shift - 1)) & 1;
+        return ((uint32_t)x >> shift) | (x << (32 - shift));
+    }
+}
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
new file mode 100644
index 0000000..a6ba991
--- /dev/null
+++ b/target-unicore32/translate.c
@@ -0,0 +1,2105 @@
+/*
+ *  UniCore32 translation
+ *
+ * Copyright (C) 2010-2011 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "tcg-op.h"
+#include "qemu-log.h"
+
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+/* internal defines */
+typedef struct DisasContext {
+    target_ulong pc;
+    int is_jmp;
+    /* Nonzero if this instruction has been conditionally skipped.  */
+    int condjmp;
+    /* The label that will be jumped to when the instruction is skipped.  */
+    int condlabel;
+    struct TranslationBlock *tb;
+    int singlestep_enabled;
+} DisasContext;
+
+#define IS_USER(s) 1
+
+/* These instructions trap after executing, so defer them until after the
+   conditional executions state has been updated.  */
+#define DISAS_SYSCALL 5
+
+static TCGv_ptr cpu_env;
+static TCGv_i32 cpu_R[32];
+
+/* FIXME:  These should be removed.  */
+static TCGv cpu_F0s, cpu_F1s;
+static TCGv_i64 cpu_F0d, cpu_F1d;
+
+#include "gen-icount.h"
+
+static const char *regnames[] = {
+      "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
+      "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
+      "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+      "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" };
+
+/* initialize TCG globals.  */
+void uc32_translate_init(void)
+{
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+    for (i = 0; i < 32; i++) {
+        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
+                                offsetof(CPUState, regs[i]), regnames[i]);
+    }
+
+#define GEN_HELPER 2
+#include "helper.h"
+}
+
+static int num_temps;
+
+/* Allocate a temporary variable.  */
+static TCGv_i32 new_tmp(void)
+{
+    num_temps++;
+    return tcg_temp_new_i32();
+}
+
+/* Release a temporary variable.  */
+static void dead_tmp(TCGv tmp)
+{
+    tcg_temp_free(tmp);
+    num_temps--;
+}
+
+static inline TCGv load_cpu_offset(int offset)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_ld_i32(tmp, cpu_env, offset);
+    return tmp;
+}
+
+#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
+
+static inline void store_cpu_offset(TCGv var, int offset)
+{
+    tcg_gen_st_i32(var, cpu_env, offset);
+    dead_tmp(var);
+}
+
+#define store_cpu_field(var, name) \
+    store_cpu_offset(var, offsetof(CPUState, name))
+
+/* Set a variable to the value of a CPU register.  */
+static void load_reg_var(DisasContext *s, TCGv var, int reg)
+{
+    if (reg == 31) {
+        uint32_t addr;
+        /* normaly, since we updated PC */
+        addr = (long)s->pc;
+        tcg_gen_movi_i32(var, addr);
+    } else {
+        tcg_gen_mov_i32(var, cpu_R[reg]);
+    }
+}
+
+/* Create a new temporary and set it to the value of a CPU register.  */
+static inline TCGv load_reg(DisasContext *s, int reg)
+{
+    TCGv tmp = new_tmp();
+    load_reg_var(s, tmp, reg);
+    return tmp;
+}
+
+/* Set a CPU register.  The source must be a temporary and will be
+   marked as dead.  */
+static void store_reg(DisasContext *s, int reg, TCGv var)
+{
+    if (reg == 31) {
+        tcg_gen_andi_i32(var, var, ~3);
+        s->is_jmp = DISAS_JUMP;
+    }
+    tcg_gen_mov_i32(cpu_R[reg], var);
+    dead_tmp(var);
+}
+
+/* Value extensions.  */
+#define gen_uxtb(var)           tcg_gen_ext8u_i32(var, var)
+#define gen_uxth(var)           tcg_gen_ext16u_i32(var, var)
+#define gen_sxtb(var)           tcg_gen_ext8s_i32(var, var)
+#define gen_sxth(var)           tcg_gen_ext16s_i32(var, var)
+
+#define UCOP_REG_M              (((insn) >>  0) & 0x1f)
+#define UCOP_REG_N              (((insn) >> 19) & 0x1f)
+#define UCOP_REG_D              (((insn) >> 14) & 0x1f)
+#define UCOP_REG_S              (((insn) >>  9) & 0x1f)
+#define UCOP_REG_LO             (((insn) >> 14) & 0x1f)
+#define UCOP_REG_HI             (((insn) >>  9) & 0x1f)
+#define UCOP_SH_OP              (((insn) >>  6) & 0x03)
+#define UCOP_SH_IM              (((insn) >>  9) & 0x1f)
+#define UCOP_OPCODES            (((insn) >> 25) & 0x0f)
+#define UCOP_IMM_9              (((insn) >>  0) & 0x1ff)
+#define UCOP_IMM10              (((insn) >>  0) & 0x3ff)
+#define UCOP_IMM14              (((insn) >>  0) & 0x3fff)
+#define UCOP_COND               (((insn) >> 25) & 0x0f)
+#define UCOP_CMOV_COND          (((insn) >> 19) & 0x0f)
+#define UCOP_CPNUM              (((insn) >> 10) & 0x0f)
+#define UCOP_UCF64_FMT          (((insn) >> 24) & 0x03)
+#define UCOP_UCF64_FUNC         (((insn) >>  6) & 0x0f)
+#define UCOP_UCF64_COND         (((insn) >>  6) & 0x0f)
+
+#define UCOP_SET(i)             ((insn) & (1 << (i)))
+#define UCOP_SET_P              UCOP_SET(28)
+#define UCOP_SET_U              UCOP_SET(27)
+#define UCOP_SET_B              UCOP_SET(26)
+#define UCOP_SET_W              UCOP_SET(25)
+#define UCOP_SET_L              UCOP_SET(24)
+#define UCOP_SET_S              UCOP_SET(24)
+
+#define ILLEGAL         cpu_abort(env,                                  \
+                        "Illegal UniCore32 instruction %x at line %d!", \
+                        insn, __LINE__)
+
+static inline void gen_set_asr(TCGv var, uint32_t mask)
+{
+    TCGv tmp_mask = tcg_const_i32(mask);
+    gen_helper_asr_write(var, tmp_mask);
+    tcg_temp_free_i32(tmp_mask);
+}
+/* Set NZCV flags from the high 4 bits of var.  */
+#define gen_set_nzcv(var) gen_set_asr(var, ASR_NZCV)
+
+static void gen_exception(int excp)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_movi_i32(tmp, excp);
+    gen_helper_exception(tmp);
+    dead_tmp(tmp);
+}
+
+/* FIXME: Most targets have native widening multiplication.
+   It would be good to use that instead of a full wide multiply.  */
+/* 32x32->64 multiply.  Marks inputs as dead.  */
+static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
+{
+    TCGv_i64 tmp1 = tcg_temp_new_i64();
+    TCGv_i64 tmp2 = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(tmp1, a);
+    dead_tmp(a);
+    tcg_gen_extu_i32_i64(tmp2, b);
+    dead_tmp(b);
+    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
+    tcg_temp_free_i64(tmp2);
+    return tmp1;
+}
+
+static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
+{
+    TCGv_i64 tmp1 = tcg_temp_new_i64();
+    TCGv_i64 tmp2 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(tmp1, a);
+    dead_tmp(a);
+    tcg_gen_ext_i32_i64(tmp2, b);
+    dead_tmp(b);
+    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
+    tcg_temp_free_i64(tmp2);
+    return tmp1;
+}
+
+#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
+
+/* Set CF to the top bit of var.  */
+static void gen_set_CF_bit31(TCGv var)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_shri_i32(tmp, var, 31);
+    gen_set_CF(tmp);
+    dead_tmp(tmp);
+}
+
+/* Set N and Z flags from var.  */
+static inline void gen_logic_CC(TCGv var)
+{
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
+}
+
+/* dest = T0 + T1 + CF. */
+static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
+{
+    TCGv tmp;
+    tcg_gen_add_i32(dest, t0, t1);
+    tmp = load_cpu_field(CF);
+    tcg_gen_add_i32(dest, dest, tmp);
+    dead_tmp(tmp);
+}
+
+/* dest = T0 - T1 + CF - 1.  */
+static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
+{
+    TCGv tmp;
+    tcg_gen_sub_i32(dest, t0, t1);
+    tmp = load_cpu_field(CF);
+    tcg_gen_add_i32(dest, dest, tmp);
+    tcg_gen_subi_i32(dest, dest, 1);
+    dead_tmp(tmp);
+}
+
+static void shifter_out_im(TCGv var, int shift)
+{
+    TCGv tmp = new_tmp();
+    if (shift == 0) {
+        tcg_gen_andi_i32(tmp, var, 1);
+    } else {
+        tcg_gen_shri_i32(tmp, var, shift);
+        if (shift != 31) {
+            tcg_gen_andi_i32(tmp, tmp, 1);
+        }
+    }
+    gen_set_CF(tmp);
+    dead_tmp(tmp);
+}
+
+/* Shift by immediate.  Includes special handling for shift == 0.  */
+static inline void gen_uc32_shift_im(TCGv var, int shiftop, int shift,
+        int flags)
+{
+    switch (shiftop) {
+    case 0: /* LSL */
+        if (shift != 0) {
+            if (flags) {
+                shifter_out_im(var, 32 - shift);
+            }
+            tcg_gen_shli_i32(var, var, shift);
+        }
+        break;
+    case 1: /* LSR */
+        if (shift == 0) {
+            if (flags) {
+                tcg_gen_shri_i32(var, var, 31);
+                gen_set_CF(var);
+            }
+            tcg_gen_movi_i32(var, 0);
+        } else {
+            if (flags) {
+                shifter_out_im(var, shift - 1);
+            }
+            tcg_gen_shri_i32(var, var, shift);
+        }
+        break;
+    case 2: /* ASR */
+        if (shift == 0) {
+            shift = 32;
+        }
+        if (flags) {
+            shifter_out_im(var, shift - 1);
+        }
+        if (shift == 32) {
+            shift = 31;
+        }
+        tcg_gen_sari_i32(var, var, shift);
+        break;
+    case 3: /* ROR/RRX */
+        if (shift != 0) {
+            if (flags) {
+                shifter_out_im(var, shift - 1);
+            }
+            tcg_gen_rotri_i32(var, var, shift); break;
+        } else {
+            TCGv tmp = load_cpu_field(CF);
+            if (flags) {
+                shifter_out_im(var, 0);
+            }
+            tcg_gen_shri_i32(var, var, 1);
+            tcg_gen_shli_i32(tmp, tmp, 31);
+            tcg_gen_or_i32(var, var, tmp);
+            dead_tmp(tmp);
+        }
+    }
+};
+
+static inline void gen_uc32_shift_reg(TCGv var, int shiftop,
+                                     TCGv shift, int flags)
+{
+    if (flags) {
+        switch (shiftop) {
+        case 0:
+            gen_helper_shl_cc(var, var, shift);
+            break;
+        case 1:
+            gen_helper_shr_cc(var, var, shift);
+            break;
+        case 2:
+            gen_helper_sar_cc(var, var, shift);
+            break;
+        case 3:
+            gen_helper_ror_cc(var, var, shift);
+            break;
+        }
+    } else {
+        switch (shiftop) {
+        case 0:
+            gen_helper_shl(var, var, shift);
+            break;
+        case 1:
+            gen_helper_shr(var, var, shift);
+            break;
+        case 2:
+            gen_helper_sar(var, var, shift);
+            break;
+        case 3:
+            tcg_gen_andi_i32(shift, shift, 0x1f);
+            tcg_gen_rotr_i32(var, var, shift);
+            break;
+        }
+    }
+    dead_tmp(shift);
+}
+
+static void gen_test_cc(int cc, int label)
+{
+    TCGv tmp;
+    TCGv tmp2;
+    int inv;
+
+    switch (cc) {
+    case 0: /* eq: Z */
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        break;
+    case 1: /* ne: !Z */
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+        break;
+    case 2: /* cs: C */
+        tmp = load_cpu_field(CF);
+        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+        break;
+    case 3: /* cc: !C */
+        tmp = load_cpu_field(CF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        break;
+    case 4: /* mi: N */
+        tmp = load_cpu_field(NF);
+        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+        break;
+    case 5: /* pl: !N */
+        tmp = load_cpu_field(NF);
+        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+        break;
+    case 6: /* vs: V */
+        tmp = load_cpu_field(VF);
+        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+        break;
+    case 7: /* vc: !V */
+        tmp = load_cpu_field(VF);
+        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+        break;
+    case 8: /* hi: C && !Z */
+        inv = gen_new_label();
+        tmp = load_cpu_field(CF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
+        dead_tmp(tmp);
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+        gen_set_label(inv);
+        break;
+    case 9: /* ls: !C || Z */
+        tmp = load_cpu_field(CF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        dead_tmp(tmp);
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        break;
+    case 10: /* ge: N == V -> N ^ V == 0 */
+        tmp = load_cpu_field(VF);
+        tmp2 = load_cpu_field(NF);
+        tcg_gen_xor_i32(tmp, tmp, tmp2);
+        dead_tmp(tmp2);
+        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+        break;
+    case 11: /* lt: N != V -> N ^ V != 0 */
+        tmp = load_cpu_field(VF);
+        tmp2 = load_cpu_field(NF);
+        tcg_gen_xor_i32(tmp, tmp, tmp2);
+        dead_tmp(tmp2);
+        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+        break;
+    case 12: /* gt: !Z && N == V */
+        inv = gen_new_label();
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
+        dead_tmp(tmp);
+        tmp = load_cpu_field(VF);
+        tmp2 = load_cpu_field(NF);
+        tcg_gen_xor_i32(tmp, tmp, tmp2);
+        dead_tmp(tmp2);
+        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+        gen_set_label(inv);
+        break;
+    case 13: /* le: Z || N != V */
+        tmp = load_cpu_field(ZF);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+        dead_tmp(tmp);
+        tmp = load_cpu_field(VF);
+        tmp2 = load_cpu_field(NF);
+        tcg_gen_xor_i32(tmp, tmp, tmp2);
+        dead_tmp(tmp2);
+        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+        break;
+    default:
+        fprintf(stderr, "Bad condition code 0x%x\n", cc);
+        abort();
+    }
+    dead_tmp(tmp);
+}
+
+static const uint8_t table_logic_cc[16] = {
+    1, /* and */    1, /* xor */    0, /* sub */    0, /* rsb */
+    0, /* add */    0, /* adc */    0, /* sbc */    0, /* rsc */
+    1, /* andl */   1, /* xorl */   0, /* cmp */    0, /* cmn */
+    1, /* orr */    1, /* mov */    1, /* bic */    1, /* mvn */
+};
+
+/* Set PC state from an immediate address.  */
+static inline void gen_bx_im(DisasContext *s, uint32_t addr)
+{
+    s->is_jmp = DISAS_UPDATE;
+    tcg_gen_movi_i32(cpu_R[31], addr & ~3);
+}
+
+/* Set PC state from var.  var is marked as dead.  */
+static inline void gen_bx(DisasContext *s, TCGv var)
+{
+    s->is_jmp = DISAS_UPDATE;
+    tcg_gen_andi_i32(cpu_R[31], var, ~3);
+    dead_tmp(var);
+}
+
+static inline void store_reg_bx(DisasContext *s, int reg, TCGv var)
+{
+    store_reg(s, reg, var);
+}
+
+static inline TCGv gen_ld8s(TCGv addr, int index)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_qemu_ld8s(tmp, addr, index);
+    return tmp;
+}
+
+static inline TCGv gen_ld8u(TCGv addr, int index)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_qemu_ld8u(tmp, addr, index);
+    return tmp;
+}
+
+static inline TCGv gen_ld16s(TCGv addr, int index)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_qemu_ld16s(tmp, addr, index);
+    return tmp;
+}
+
+static inline TCGv gen_ld16u(TCGv addr, int index)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_qemu_ld16u(tmp, addr, index);
+    return tmp;
+}
+
+static inline TCGv gen_ld32(TCGv addr, int index)
+{
+    TCGv tmp = new_tmp();
+    tcg_gen_qemu_ld32u(tmp, addr, index);
+    return tmp;
+}
+
+static inline TCGv_i64 gen_ld64(TCGv addr, int index)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
+    tcg_gen_qemu_ld64(tmp, addr, index);
+    return tmp;
+}
+
+static inline void gen_st8(TCGv val, TCGv addr, int index)
+{
+    tcg_gen_qemu_st8(val, addr, index);
+    dead_tmp(val);
+}
+
+static inline void gen_st16(TCGv val, TCGv addr, int index)
+{
+    tcg_gen_qemu_st16(val, addr, index);
+    dead_tmp(val);
+}
+
+static inline void gen_st32(TCGv val, TCGv addr, int index)
+{
+    tcg_gen_qemu_st32(val, addr, index);
+    dead_tmp(val);
+}
+
+static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
+{
+    tcg_gen_qemu_st64(val, addr, index);
+    tcg_temp_free_i64(val);
+}
+
+static inline void gen_set_pc_im(uint32_t val)
+{
+    tcg_gen_movi_i32(cpu_R[31], val);
+}
+
+/* Force a TB lookup after an instruction that changes the CPU state.  */
+static inline void gen_lookup_tb(DisasContext *s)
+{
+    tcg_gen_movi_i32(cpu_R[31], s->pc & ~1);
+    s->is_jmp = DISAS_UPDATE;
+}
+
+static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
+        TCGv var)
+{
+    int val;
+    TCGv offset;
+
+    if (UCOP_SET(29)) {
+        /* immediate */
+        val = UCOP_IMM14;
+        if (!UCOP_SET_U) {
+            val = -val;
+        }
+        if (val != 0) {
+            tcg_gen_addi_i32(var, var, val);
+        }
+    } else {
+        /* shift/register */
+        offset = load_reg(s, UCOP_REG_M);
+        gen_uc32_shift_im(offset, UCOP_SH_OP, UCOP_SH_IM, 0);
+        if (!UCOP_SET_U) {
+            tcg_gen_sub_i32(var, var, offset);
+        } else {
+            tcg_gen_add_i32(var, var, offset);
+        }
+        dead_tmp(offset);
+    }
+}
+
+static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
+        TCGv var)
+{
+    int val;
+    TCGv offset;
+
+    if (UCOP_SET(26)) {
+        /* immediate */
+        val = (insn & 0x1f) | ((insn >> 4) & 0x3e0);
+        if (!UCOP_SET_U) {
+            val = -val;
+        }
+        if (val != 0) {
+            tcg_gen_addi_i32(var, var, val);
+        }
+    } else {
+        /* register */
+        offset = load_reg(s, UCOP_REG_M);
+        if (!UCOP_SET_U) {
+            tcg_gen_sub_i32(var, var, offset);
+        } else {
+            tcg_gen_add_i32(var, var, offset);
+        }
+        dead_tmp(offset);
+    }
+}
+
+static inline long ucf64_reg_offset(int reg)
+{
+    if (reg & 1) {
+        return offsetof(CPUState, ucf64.regs[reg >> 1])
+          + offsetof(CPU_DoubleU, l.upper);
+    } else {
+        return offsetof(CPUState, ucf64.regs[reg >> 1])
+          + offsetof(CPU_DoubleU, l.lower);
+    }
+}
+
+#define ucf64_gen_ld32(reg)      load_cpu_offset(ucf64_reg_offset(reg))
+#define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg))
+
+/* UniCore-F64 single load/store I_offset */
+static void do_ucf64_ldst_i(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    int offset;
+    TCGv tmp;
+    TCGv addr;
+
+    addr = load_reg(s, UCOP_REG_N);
+    if (!UCOP_SET_P && !UCOP_SET_W) {
+        ILLEGAL;
+    }
+
+    if (UCOP_SET_P) {
+        offset = UCOP_IMM10 << 2;
+        if (!UCOP_SET_U) {
+            offset = -offset;
+        }
+        if (offset != 0) {
+            tcg_gen_addi_i32(addr, addr, offset);
+        }
+    }
+
+    if (UCOP_SET_L) { /* load */
+        tmp = gen_ld32(addr, IS_USER(s));
+        ucf64_gen_st32(tmp, UCOP_REG_D);
+    } else { /* store */
+        tmp = ucf64_gen_ld32(UCOP_REG_D);
+        gen_st32(tmp, addr, IS_USER(s));
+    }
+
+    if (!UCOP_SET_P) {
+        offset = UCOP_IMM10 << 2;
+        if (!UCOP_SET_U) {
+            offset = -offset;
+        }
+        if (offset != 0) {
+            tcg_gen_addi_i32(addr, addr, offset);
+        }
+    }
+    if (UCOP_SET_W) {
+        store_reg(s, UCOP_REG_N, addr);
+    } else {
+        dead_tmp(addr);
+    }
+}
+
+/* UniCore-F64 load/store multiple words */
+static void do_ucf64_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    unsigned int i;
+    int j, n, freg;
+    TCGv tmp;
+    TCGv addr;
+
+    if (UCOP_REG_D != 0) {
+        ILLEGAL;
+    }
+    if (UCOP_REG_N == 31) {
+        ILLEGAL;
+    }
+    if ((insn << 24) == 0) {
+        ILLEGAL;
+    }
+
+    addr = load_reg(s, UCOP_REG_N);
+
+    n = 0;
+    for (i = 0; i < 8; i++) {
+        if (UCOP_SET(i)) {
+            n++;
+        }
+    }
+
+    if (UCOP_SET_U) {
+        if (UCOP_SET_P) { /* pre increment */
+            tcg_gen_addi_i32(addr, addr, 4);
+        } /* unnecessary to do anything when post increment */
+    } else {
+        if (UCOP_SET_P) { /* pre decrement */
+            tcg_gen_addi_i32(addr, addr, -(n * 4));
+        } else { /* post decrement */
+            if (n != 1) {
+                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+            }
+        }
+    }
+
+    freg = ((insn >> 8) & 3) << 3; /* freg should be 0, 8, 16, 24 */
+
+    for (i = 0, j = 0; i < 8; i++, freg++) {
+        if (!UCOP_SET(i)) {
+            continue;
+        }
+
+        if (UCOP_SET_L) { /* load */
+            tmp = gen_ld32(addr, IS_USER(s));
+            ucf64_gen_st32(tmp, freg);
+        } else { /* store */
+            tmp = ucf64_gen_ld32(freg);
+            gen_st32(tmp, addr, IS_USER(s));
+        }
+
+        j++;
+        /* unnecessary to add after the last transfer */
+        if (j != n) {
+            tcg_gen_addi_i32(addr, addr, 4);
+        }
+    }
+
+    if (UCOP_SET_W) { /* write back */
+        if (UCOP_SET_U) {
+            if (!UCOP_SET_P) { /* post increment */
+                tcg_gen_addi_i32(addr, addr, 4);
+            } /* unnecessary to do anything when pre increment */
+        } else {
+            if (UCOP_SET_P) {
+                /* pre decrement */
+                if (n != 1) {
+                    tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+                }
+            } else {
+                /* post decrement */
+                tcg_gen_addi_i32(addr, addr, -(n * 4));
+            }
+        }
+        store_reg(s, UCOP_REG_N, addr);
+    } else {
+        dead_tmp(addr);
+    }
+}
+
+/* UniCore-F64 mrc/mcr */
+static void do_ucf64_trans(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    TCGv tmp;
+
+    if ((insn & 0xfe0003ff) == 0xe2000000) {
+        /* control register */
+        if ((UCOP_REG_N != UC32_UCF64_FPSCR) || (UCOP_REG_D == 31)) {
+            ILLEGAL;
+        }
+        if (UCOP_SET(24)) {
+            /* CFF */
+            tmp = new_tmp();
+            gen_helper_ucf64_get_fpscr(tmp, cpu_env);
+            store_reg(s, UCOP_REG_D, tmp);
+        } else {
+            /* CTF */
+            tmp = load_reg(s, UCOP_REG_D);
+            gen_helper_ucf64_set_fpscr(cpu_env, tmp);
+            dead_tmp(tmp);
+            gen_lookup_tb(s);
+        }
+        return;
+    }
+    if ((insn & 0xfe0003ff) == 0xe0000000) {
+        /* general register */
+        if (UCOP_REG_D == 31) {
+            ILLEGAL;
+        }
+        if (UCOP_SET(24)) { /* MFF */
+            tmp = ucf64_gen_ld32(UCOP_REG_N);
+            store_reg(s, UCOP_REG_D, tmp);
+        } else { /* MTF */
+            tmp = load_reg(s, UCOP_REG_D);
+            ucf64_gen_st32(tmp, UCOP_REG_N);
+        }
+        return;
+    }
+    if ((insn & 0xfb000000) == 0xe9000000) {
+        /* MFFC */
+        if (UCOP_REG_D != 31) {
+            ILLEGAL;
+        }
+        if (UCOP_UCF64_COND & 0x8) {
+            ILLEGAL;
+        }
+
+        tmp = new_tmp();
+        tcg_gen_movi_i32(tmp, UCOP_UCF64_COND);
+        if (UCOP_SET(26)) {
+            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
+            tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, tmp, cpu_env);
+        } else {
+            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
+            tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, tmp, cpu_env);
+        }
+        dead_tmp(tmp);
+        return;
+    }
+    ILLEGAL;
+}
+
+/* UniCore-F64 convert instructions */
+static void do_ucf64_fcvt(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    if (UCOP_UCF64_FMT == 3) {
+        ILLEGAL;
+    }
+    if (UCOP_REG_N != 0) {
+        ILLEGAL;
+    }
+    switch (UCOP_UCF64_FUNC) {
+    case 0: /* cvt.s */
+        switch (UCOP_UCF64_FMT) {
+        case 1 /* d */:
+            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_df2sf(cpu_F0s, cpu_F0d, cpu_env);
+            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+        case 2 /* w */:
+            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_si2sf(cpu_F0s, cpu_F0s, cpu_env);
+            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+        default /* s */:
+            ILLEGAL;
+            break;
+        }
+        break;
+    case 1: /* cvt.d */
+        switch (UCOP_UCF64_FMT) {
+        case 0 /* s */:
+            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_sf2df(cpu_F0d, cpu_F0s, cpu_env);
+            tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+        case 2 /* w */:
+            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_si2df(cpu_F0d, cpu_F0s, cpu_env);
+            tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+        default /* d */:
+            ILLEGAL;
+            break;
+        }
+        break;
+    case 4: /* cvt.w */
+        switch (UCOP_UCF64_FMT) {
+        case 0 /* s */:
+            tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_sf2si(cpu_F0s, cpu_F0s, cpu_env);
+            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+        case 1 /* d */:
+            tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+            gen_helper_ucf64_df2si(cpu_F0s, cpu_F0d, cpu_env);
+            tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
+            break;
+    default /* w */:
+            ILLEGAL;
+            break;
+        }
+        break;
+    default:
+        ILLEGAL;
+    }
+}
+
+/* UniCore-F64 compare instructions */
+static void do_ucf64_fcmp(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    if (UCOP_SET(25)) {
+        ILLEGAL;
+    }
+    if (UCOP_REG_D != 0) {
+        ILLEGAL;
+    }
+
+    ILLEGAL; /* TODO */
+    if (UCOP_SET(24)) {
+        tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
+        tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+        /* gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, cpu_env); */
+    } else {
+        tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
+        tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
+        /* gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, cpu_env); */
+    }
+}
+
+#define gen_helper_ucf64_movs(x, y)      do { } while (0)
+#define gen_helper_ucf64_movd(x, y)      do { } while (0)
+
+#define UCF64_OP1(name)    do {                           \
+        if (UCOP_REG_N != 0) {                            \
+            ILLEGAL;                                      \
+        }                                                 \
+        switch (UCOP_UCF64_FMT) {                         \
+        case 0 /* s */:                                   \
+            tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_M)); \
+            gen_helper_ucf64_##name##s(cpu_F0s, cpu_F0s); \
+            tcg_gen_st_i32(cpu_F0s, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_D)); \
+            break;                                        \
+        case 1 /* d */:                                   \
+            tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_M)); \
+            gen_helper_ucf64_##name##d(cpu_F0d, cpu_F0d); \
+            tcg_gen_st_i64(cpu_F0d, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_D)); \
+            break;                                        \
+        case 2 /* w */:                                   \
+            ILLEGAL;                                      \
+            break;                                        \
+        }                                                 \
+    } while (0)
+
+#define UCF64_OP2(name)    do {                           \
+        switch (UCOP_UCF64_FMT) {                         \
+        case 0 /* s */:                                   \
+            tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_N)); \
+            tcg_gen_ld_i32(cpu_F1s, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_M)); \
+            gen_helper_ucf64_##name##s(cpu_F0s,           \
+                           cpu_F0s, cpu_F1s, cpu_env);    \
+            tcg_gen_st_i32(cpu_F0s, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_D)); \
+            break;                                        \
+        case 1 /* d */:                                   \
+            tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_N)); \
+            tcg_gen_ld_i64(cpu_F1d, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_M)); \
+            gen_helper_ucf64_##name##d(cpu_F0d,           \
+                           cpu_F0d, cpu_F1d, cpu_env);    \
+            tcg_gen_st_i64(cpu_F0d, cpu_env,              \
+                           ucf64_reg_offset(UCOP_REG_D)); \
+            break;                                        \
+        case 2 /* w */:                                   \
+            ILLEGAL;                                      \
+            break;                                        \
+        }                                                 \
+    } while (0)
+
+/* UniCore-F64 data processing */
+static void do_ucf64_datap(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    if (UCOP_UCF64_FMT == 3) {
+        ILLEGAL;
+    }
+    switch (UCOP_UCF64_FUNC) {
+    case 0: /* add */
+        UCF64_OP2(add);
+        break;
+    case 1: /* sub */
+        UCF64_OP2(sub);
+        break;
+    case 2: /* mul */
+        UCF64_OP2(mul);
+        break;
+    case 4: /* div */
+        UCF64_OP2(div);
+        break;
+    case 5: /* abs */
+        UCF64_OP1(abs);
+        break;
+    case 6: /* mov */
+        UCF64_OP1(mov);
+        break;
+    case 7: /* neg */
+        UCF64_OP1(neg);
+        break;
+    default:
+        ILLEGAL;
+    }
+}
+
+/* Disassemble an F64 instruction */
+static void disas_ucf64_insn(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    if (!UCOP_SET(29)) {
+        if (UCOP_SET(26)) {
+            do_ucf64_ldst_m(env, s, insn);
+        } else {
+            do_ucf64_ldst_i(env, s, insn);
+        }
+    } else {
+        if (UCOP_SET(5)) {
+            switch ((insn >> 26) & 0x3) {
+            case 0:
+                do_ucf64_datap(env, s, insn);
+                break;
+            case 1:
+                ILLEGAL;
+                break;
+            case 2:
+                do_ucf64_fcvt(env, s, insn);
+                break;
+            case 3:
+                do_ucf64_fcmp(env, s, insn);
+                break;
+            }
+        } else {
+            do_ucf64_trans(env, s, insn);
+        }
+    }
+}
+
+static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
+{
+    TranslationBlock *tb;
+
+    tb = s->tb;
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+        tcg_gen_goto_tb(n);
+        gen_set_pc_im(dest);
+        tcg_gen_exit_tb((long)tb + n);
+    } else {
+        gen_set_pc_im(dest);
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
+{
+    if (unlikely(s->singlestep_enabled)) {
+        /* An indirect jump so that we still trigger the debug exception.  */
+        gen_bx_im(s, dest);
+    } else {
+        gen_goto_tb(s, 0, dest);
+        s->is_jmp = DISAS_TB_JUMP;
+    }
+}
+
+static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
+{
+    if (x) {
+        tcg_gen_sari_i32(t0, t0, 16);
+    } else {
+        gen_sxth(t0);
+    }
+    if (y) {
+        tcg_gen_sari_i32(t1, t1, 16);
+    } else {
+        gen_sxth(t1);
+    }
+    tcg_gen_mul_i32(t0, t0, t1);
+}
+
+/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
+static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0)
+{
+    TCGv tmp;
+    if (bsr) {
+        /* ??? This is also undefined in system mode.  */
+        if (IS_USER(s)) {
+            return 1;
+        }
+
+        tmp = load_cpu_field(bsr);
+        tcg_gen_andi_i32(tmp, tmp, ~mask);
+        tcg_gen_andi_i32(t0, t0, mask);
+        tcg_gen_or_i32(tmp, tmp, t0);
+        store_cpu_field(tmp, bsr);
+    } else {
+        gen_set_asr(t0, mask);
+    }
+    dead_tmp(t0);
+    gen_lookup_tb(s);
+    return 0;
+}
+
+/* Generate an old-style exception return. Marks pc as dead. */
+static void gen_exception_return(DisasContext *s, TCGv pc)
+{
+    TCGv tmp;
+    store_reg(s, 31, pc);
+    tmp = load_cpu_field(bsr);
+    gen_set_asr(tmp, 0xffffffff);
+    dead_tmp(tmp);
+    s->is_jmp = DISAS_UPDATE;
+}
+
+static void disas_coproc_insn(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    switch (UCOP_CPNUM) {
+    case 2:
+        disas_ucf64_insn(env, s, insn);
+        break;
+    default:
+        /* Unknown coprocessor. */
+        cpu_abort(env, "Unknown coprocessor!");
+    }
+}
+
+
+/* Store a 64-bit value to a register pair.  Clobbers val.  */
+static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
+{
+    TCGv tmp;
+    tmp = new_tmp();
+    tcg_gen_trunc_i64_i32(tmp, val);
+    store_reg(s, rlow, tmp);
+    tmp = new_tmp();
+    tcg_gen_shri_i64(val, val, 32);
+    tcg_gen_trunc_i64_i32(tmp, val);
+    store_reg(s, rhigh, tmp);
+}
+
+/* load and add a 64-bit value from a register pair.  */
+static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
+{
+    TCGv_i64 tmp;
+    TCGv tmpl;
+    TCGv tmph;
+
+    /* Load 64-bit value rd:rn.  */
+    tmpl = load_reg(s, rlow);
+    tmph = load_reg(s, rhigh);
+    tmp = tcg_temp_new_i64();
+    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
+    dead_tmp(tmpl);
+    dead_tmp(tmph);
+    tcg_gen_add_i64(val, val, tmp);
+    tcg_temp_free_i64(tmp);
+}
+
+/* data processing instructions */
+static void do_datap(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    TCGv tmp;
+    TCGv tmp2;
+    int logic_cc;
+
+    if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) {
+        if (UCOP_SET(23)) { /* CMOV instructions */
+            if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) {
+                ILLEGAL;
+            }
+            /* if not always execute, we generate a conditional jump to
+               next instruction */
+            s->condlabel = gen_new_label();
+            gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel);
+            s->condjmp = 1;
+        }
+    }
+
+    logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24);
+
+    if (UCOP_SET(29)) {
+        unsigned int val;
+        /* immediate operand */
+        val = UCOP_IMM_9;
+        if (UCOP_SH_IM) {
+            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
+        }
+        tmp2 = new_tmp();
+        tcg_gen_movi_i32(tmp2, val);
+        if (logic_cc && UCOP_SH_IM) {
+            gen_set_CF_bit31(tmp2);
+        }
+   } else {
+        /* register */
+        tmp2 = load_reg(s, UCOP_REG_M);
+        if (UCOP_SET(5)) {
+            tmp = load_reg(s, UCOP_REG_S);
+            gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc);
+        } else {
+            gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc);
+        }
+    }
+
+    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
+        tmp = load_reg(s, UCOP_REG_N);
+    } else {
+        TCGV_UNUSED(tmp);
+    }
+
+    switch (UCOP_OPCODES) {
+    case 0x00:
+        tcg_gen_and_i32(tmp, tmp, tmp2);
+        if (logic_cc) {
+            gen_logic_CC(tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x01:
+        tcg_gen_xor_i32(tmp, tmp, tmp2);
+        if (logic_cc) {
+            gen_logic_CC(tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x02:
+        if (UCOP_SET_S && UCOP_REG_D == 31) {
+            /* SUBS r31, ... is used for exception return.  */
+            if (IS_USER(s)) {
+                ILLEGAL;
+            }
+            gen_helper_sub_cc(tmp, tmp, tmp2);
+            gen_exception_return(s, tmp);
+        } else {
+            if (UCOP_SET_S) {
+                gen_helper_sub_cc(tmp, tmp, tmp2);
+            } else {
+                tcg_gen_sub_i32(tmp, tmp, tmp2);
+            }
+            store_reg_bx(s, UCOP_REG_D, tmp);
+        }
+        break;
+    case 0x03:
+        if (UCOP_SET_S) {
+            gen_helper_sub_cc(tmp, tmp2, tmp);
+        } else {
+            tcg_gen_sub_i32(tmp, tmp2, tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x04:
+        if (UCOP_SET_S) {
+            gen_helper_add_cc(tmp, tmp, tmp2);
+        } else {
+            tcg_gen_add_i32(tmp, tmp, tmp2);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x05:
+        if (UCOP_SET_S) {
+            gen_helper_adc_cc(tmp, tmp, tmp2);
+        } else {
+            gen_add_carry(tmp, tmp, tmp2);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x06:
+        if (UCOP_SET_S) {
+            gen_helper_sbc_cc(tmp, tmp, tmp2);
+        } else {
+            gen_sub_carry(tmp, tmp, tmp2);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x07:
+        if (UCOP_SET_S) {
+            gen_helper_sbc_cc(tmp, tmp2, tmp);
+        } else {
+            gen_sub_carry(tmp, tmp2, tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x08:
+        if (UCOP_SET_S) {
+            tcg_gen_and_i32(tmp, tmp, tmp2);
+            gen_logic_CC(tmp);
+        }
+        dead_tmp(tmp);
+        break;
+    case 0x09:
+        if (UCOP_SET_S) {
+            tcg_gen_xor_i32(tmp, tmp, tmp2);
+            gen_logic_CC(tmp);
+        }
+        dead_tmp(tmp);
+        break;
+    case 0x0a:
+        if (UCOP_SET_S) {
+            gen_helper_sub_cc(tmp, tmp, tmp2);
+        }
+        dead_tmp(tmp);
+        break;
+    case 0x0b:
+        if (UCOP_SET_S) {
+            gen_helper_add_cc(tmp, tmp, tmp2);
+        }
+        dead_tmp(tmp);
+        break;
+    case 0x0c:
+        tcg_gen_or_i32(tmp, tmp, tmp2);
+        if (logic_cc) {
+            gen_logic_CC(tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    case 0x0d:
+        if (logic_cc && UCOP_REG_D == 31) {
+            /* MOVS r31, ... is used for exception return.  */
+            if (IS_USER(s)) {
+                ILLEGAL;
+            }
+            gen_exception_return(s, tmp2);
+        } else {
+            if (logic_cc) {
+                gen_logic_CC(tmp2);
+            }
+            store_reg_bx(s, UCOP_REG_D, tmp2);
+        }
+        break;
+    case 0x0e:
+        tcg_gen_andc_i32(tmp, tmp, tmp2);
+        if (logic_cc) {
+            gen_logic_CC(tmp);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp);
+        break;
+    default:
+    case 0x0f:
+        tcg_gen_not_i32(tmp2, tmp2);
+        if (logic_cc) {
+            gen_logic_CC(tmp2);
+        }
+        store_reg_bx(s, UCOP_REG_D, tmp2);
+        break;
+    }
+    if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
+        dead_tmp(tmp2);
+    }
+}
+
+/* multiply */
+static void do_mult(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    TCGv tmp;
+    TCGv tmp2;
+    TCGv_i64 tmp64;
+
+    if (UCOP_SET(27)) {
+        /* 64 bit mul */
+        tmp = load_reg(s, UCOP_REG_M);
+        tmp2 = load_reg(s, UCOP_REG_N);
+        if (UCOP_SET(26)) {
+            tmp64 = gen_muls_i64_i32(tmp, tmp2);
+        } else {
+            tmp64 = gen_mulu_i64_i32(tmp, tmp2);
+        }
+        if (UCOP_SET(25)) { /* mult accumulate */
+            gen_addq(s, tmp64, UCOP_REG_LO, UCOP_REG_HI);
+        }
+        gen_storeq_reg(s, UCOP_REG_LO, UCOP_REG_HI, tmp64);
+        tcg_temp_free_i64(tmp64);
+    } else {
+        /* 32 bit mul */
+        tmp = load_reg(s, UCOP_REG_M);
+        tmp2 = load_reg(s, UCOP_REG_N);
+        tcg_gen_mul_i32(tmp, tmp, tmp2);
+        dead_tmp(tmp2);
+        if (UCOP_SET(25)) {
+            /* Add */
+            tmp2 = load_reg(s, UCOP_REG_S);
+            tcg_gen_add_i32(tmp, tmp, tmp2);
+            dead_tmp(tmp2);
+        }
+        if (UCOP_SET_S) {
+            gen_logic_CC(tmp);
+        }
+        store_reg(s, UCOP_REG_D, tmp);
+    }
+}
+
+/* miscellaneous instructions */
+static void do_misc(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    unsigned int val;
+    TCGv tmp;
+
+    if ((insn & 0xffffffe0) == 0x10ffc120) {
+        /* Trivial implementation equivalent to bx.  */
+        tmp = load_reg(s, UCOP_REG_M);
+        gen_bx(s, tmp);
+        return;
+    }
+
+    if ((insn & 0xfbffc000) == 0x30ffc000) {
+        /* PSR = immediate */
+        val = UCOP_IMM_9;
+        if (UCOP_SH_IM) {
+            val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
+        }
+        tmp = new_tmp();
+        tcg_gen_movi_i32(tmp, val);
+        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
+            ILLEGAL;
+        }
+        return;
+    }
+
+    if ((insn & 0xfbffffe0) == 0x12ffc020) {
+        /* PSR.flag = reg */
+        tmp = load_reg(s, UCOP_REG_M);
+        if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) {
+            ILLEGAL;
+        }
+        return;
+    }
+
+    if ((insn & 0xfbffffe0) == 0x10ffc020) {
+        /* PSR = reg */
+        tmp = load_reg(s, UCOP_REG_M);
+        if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
+            ILLEGAL;
+        }
+        return;
+    }
+
+    if ((insn & 0xfbf83fff) == 0x10f80000) {
+        /* reg = PSR */
+        if (UCOP_SET_B) {
+            if (IS_USER(s)) {
+                ILLEGAL;
+            }
+            tmp = load_cpu_field(bsr);
+        } else {
+            tmp = new_tmp();
+            gen_helper_asr_read(tmp);
+        }
+        store_reg(s, UCOP_REG_D, tmp);
+        return;
+    }
+
+    if ((insn & 0xfbf83fe0) == 0x12f80120) {
+        /* clz */
+        tmp = load_reg(s, UCOP_REG_M);
+        if (UCOP_SET(26)) {
+            gen_helper_clo(tmp, tmp);
+        } else {
+            gen_helper_clz(tmp, tmp);
+        }
+        store_reg(s, UCOP_REG_D, tmp);
+        return;
+    }
+
+    /* otherwise */
+    ILLEGAL;
+}
+
+/* load/store I_offset and R_offset */
+static void do_ldst_ir(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    unsigned int i;
+    TCGv tmp;
+    TCGv tmp2;
+
+    tmp2 = load_reg(s, UCOP_REG_N);
+    i = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
+
+    /* immediate */
+    if (UCOP_SET_P) {
+        gen_add_data_offset(s, insn, tmp2);
+    }
+
+    if (UCOP_SET_L) {
+        /* load */
+        if (UCOP_SET_B) {
+            tmp = gen_ld8u(tmp2, i);
+        } else {
+            tmp = gen_ld32(tmp2, i);
+        }
+    } else {
+        /* store */
+        tmp = load_reg(s, UCOP_REG_D);
+        if (UCOP_SET_B) {
+            gen_st8(tmp, tmp2, i);
+        } else {
+            gen_st32(tmp, tmp2, i);
+        }
+    }
+    if (!UCOP_SET_P) {
+        gen_add_data_offset(s, insn, tmp2);
+        store_reg(s, UCOP_REG_N, tmp2);
+    } else if (UCOP_SET_W) {
+        store_reg(s, UCOP_REG_N, tmp2);
+    } else {
+        dead_tmp(tmp2);
+    }
+    if (UCOP_SET_L) {
+        /* Complete the load.  */
+        if (UCOP_REG_D == 31) {
+            gen_bx(s, tmp);
+        } else {
+            store_reg(s, UCOP_REG_D, tmp);
+        }
+    }
+}
+
+/* SWP instruction */
+static void do_swap(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    TCGv addr;
+    TCGv tmp;
+    TCGv tmp2;
+
+    if ((insn & 0xff003fe0) != 0x40000120) {
+        ILLEGAL;
+    }
+
+    /* ??? This is not really atomic.  However we know
+       we never have multiple CPUs running in parallel,
+       so it is good enough.  */
+    addr = load_reg(s, UCOP_REG_N);
+    tmp = load_reg(s, UCOP_REG_M);
+    if (UCOP_SET_B) {
+        tmp2 = gen_ld8u(addr, IS_USER(s));
+        gen_st8(tmp, addr, IS_USER(s));
+    } else {
+        tmp2 = gen_ld32(addr, IS_USER(s));
+        gen_st32(tmp, addr, IS_USER(s));
+    }
+    dead_tmp(addr);
+    store_reg(s, UCOP_REG_D, tmp2);
+}
+
+/* load/store hw/sb */
+static void do_ldst_hwsb(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    TCGv addr;
+    TCGv tmp;
+
+    if (UCOP_SH_OP == 0) {
+        do_swap(env, s, insn);
+        return;
+    }
+
+    addr = load_reg(s, UCOP_REG_N);
+    if (UCOP_SET_P) {
+        gen_add_datah_offset(s, insn, addr);
+    }
+
+    if (UCOP_SET_L) { /* load */
+        switch (UCOP_SH_OP) {
+        case 1:
+            tmp = gen_ld16u(addr, IS_USER(s));
+            break;
+        case 2:
+            tmp = gen_ld8s(addr, IS_USER(s));
+            break;
+        default: /* see do_swap */
+        case 3:
+            tmp = gen_ld16s(addr, IS_USER(s));
+            break;
+        }
+    } else { /* store */
+        if (UCOP_SH_OP != 1) {
+            ILLEGAL;
+        }
+        tmp = load_reg(s, UCOP_REG_D);
+        gen_st16(tmp, addr, IS_USER(s));
+    }
+    /* Perform base writeback before the loaded value to
+       ensure correct behavior with overlapping index registers. */
+    if (!UCOP_SET_P) {
+        gen_add_datah_offset(s, insn, addr);
+        store_reg(s, UCOP_REG_N, addr);
+    } else if (UCOP_SET_W) {
+        store_reg(s, UCOP_REG_N, addr);
+    } else {
+        dead_tmp(addr);
+    }
+    if (UCOP_SET_L) {
+        /* Complete the load.  */
+        store_reg(s, UCOP_REG_D, tmp);
+    }
+}
+
+/* load/store multiple words */
+static void do_ldst_m(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    unsigned int val, i;
+    int j, n, reg, user, loaded_base;
+    TCGv tmp;
+    TCGv tmp2;
+    TCGv addr;
+    TCGv loaded_var;
+
+    if (UCOP_SET(7)) {
+        ILLEGAL;
+    }
+    /* XXX: store correct base if write back */
+    user = 0;
+    if (UCOP_SET_B) { /* S bit in instruction table */
+        if (IS_USER(s)) {
+            ILLEGAL; /* only usable in supervisor mode */
+        }
+        if (UCOP_SET(18) == 0) { /* pc reg */
+            user = 1;
+        }
+    }
+
+    addr = load_reg(s, UCOP_REG_N);
+
+    /* compute total size */
+    loaded_base = 0;
+    TCGV_UNUSED(loaded_var);
+    n = 0;
+    for (i = 0; i < 6; i++) {
+        if (UCOP_SET(i)) {
+            n++;
+        }
+    }
+    for (i = 9; i < 19; i++) {
+        if (UCOP_SET(i)) {
+            n++;
+        }
+    }
+    /* XXX: test invalid n == 0 case ? */
+    if (UCOP_SET_U) {
+        if (UCOP_SET_P) {
+            /* pre increment */
+            tcg_gen_addi_i32(addr, addr, 4);
+        } else {
+            /* post increment */
+        }
+    } else {
+        if (UCOP_SET_P) {
+            /* pre decrement */
+            tcg_gen_addi_i32(addr, addr, -(n * 4));
+        } else {
+            /* post decrement */
+            if (n != 1) {
+                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+            }
+        }
+    }
+
+    j = 0;
+    reg = UCOP_SET(6) ? 16 : 0;
+    for (i = 0; i < 19; i++, reg++) {
+        if (i == 6) {
+            i = i + 3;
+        }
+        if (UCOP_SET(i)) {
+            if (UCOP_SET_L) { /* load */
+                tmp = gen_ld32(addr, IS_USER(s));
+                if (reg == 31) {
+                    gen_bx(s, tmp);
+                } else if (user) {
+                    tmp2 = tcg_const_i32(reg);
+                    gen_helper_set_user_reg(tmp2, tmp);
+                    tcg_temp_free_i32(tmp2);
+                    dead_tmp(tmp);
+                } else if (reg == UCOP_REG_N) {
+                    loaded_var = tmp;
+                    loaded_base = 1;
+                } else {
+                    store_reg(s, reg, tmp);
+                }
+            } else { /* store */
+                if (reg == 31) {
+                    /* special case: r31 = PC + 4 */
+                    val = (long)s->pc;
+                    tmp = new_tmp();
+                    tcg_gen_movi_i32(tmp, val);
+                } else if (user) {
+                    tmp = new_tmp();
+                    tmp2 = tcg_const_i32(reg);
+                    gen_helper_get_user_reg(tmp, tmp2);
+                    tcg_temp_free_i32(tmp2);
+                } else {
+                    tmp = load_reg(s, reg);
+                }
+                gen_st32(tmp, addr, IS_USER(s));
+            }
+            j++;
+            /* no need to add after the last transfer */
+            if (j != n) {
+                tcg_gen_addi_i32(addr, addr, 4);
+            }
+        }
+    }
+    if (UCOP_SET_W) { /* write back */
+        if (UCOP_SET_U) {
+            if (UCOP_SET_P) {
+                /* pre increment */
+            } else {
+                /* post increment */
+                tcg_gen_addi_i32(addr, addr, 4);
+            }
+        } else {
+            if (UCOP_SET_P) {
+                /* pre decrement */
+                if (n != 1) {
+                    tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+                }
+            } else {
+                /* post decrement */
+                tcg_gen_addi_i32(addr, addr, -(n * 4));
+            }
+        }
+        store_reg(s, UCOP_REG_N, addr);
+    } else {
+        dead_tmp(addr);
+    }
+    if (loaded_base) {
+        store_reg(s, UCOP_REG_N, loaded_var);
+    }
+    if (UCOP_SET_B && !user) {
+        /* Restore ASR from BSR.  */
+        tmp = load_cpu_field(bsr);
+        gen_set_asr(tmp, 0xffffffff);
+        dead_tmp(tmp);
+        s->is_jmp = DISAS_UPDATE;
+    }
+}
+
+/* branch (and link) */
+static void do_branch(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    unsigned int val;
+    int32_t offset;
+    TCGv tmp;
+
+    if (UCOP_COND == 0xf) {
+        ILLEGAL;
+    }
+
+    if (UCOP_COND != 0xe) {
+        /* if not always execute, we generate a conditional jump to
+           next instruction */
+        s->condlabel = gen_new_label();
+        gen_test_cc(UCOP_COND ^ 1, s->condlabel);
+        s->condjmp = 1;
+    }
+
+    val = (int32_t)s->pc;
+    if (UCOP_SET_L) {
+        tmp = new_tmp();
+        tcg_gen_movi_i32(tmp, val);
+        store_reg(s, 30, tmp);
+    }
+    offset = (((int32_t)insn << 8) >> 8);
+    val += (offset << 2); /* unicore is pc+4 */
+    gen_jmp(s, val);
+}
+
+static void disas_uc32_insn(CPUState *env, DisasContext *s)
+{
+    unsigned int insn;
+
+    insn = ldl_code(s->pc);
+    s->pc += 4;
+
+    /* UniCore instructions class:
+     * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx
+     * AAA  : see switch case
+     * BBBB : opcodes or cond or PUBW
+     * C    : S OR L
+     * D    : 8
+     * E    : 5
+     */
+    switch (insn >> 29) {
+    case 0b000:
+        if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) {
+            do_mult(env, s, insn);
+            break;
+        }
+
+        if (UCOP_SET(8)) {
+            do_misc(env, s, insn);
+            break;
+        }
+    case 0b001:
+        if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
+            do_misc(env, s, insn);
+            break;
+        }
+        do_datap(env, s, insn);
+        break;
+
+    case 0b010:
+        if (UCOP_SET(8) && UCOP_SET(5)) {
+            do_ldst_hwsb(env, s, insn);
+            break;
+        }
+        if (UCOP_SET(8) || UCOP_SET(5)) {
+            ILLEGAL;
+        }
+    case 0b011:
+        do_ldst_ir(env, s, insn);
+        break;
+
+    case 0b100:
+        if (UCOP_SET(8)) {
+            ILLEGAL; /* extended instructions */
+        }
+        do_ldst_m(env, s, insn);
+        break;
+    case 0b101:
+        do_branch(env, s, insn);
+        break;
+    case 0b110:
+        /* Coprocessor.  */
+        disas_coproc_insn(env, s, insn);
+        break;
+    case 0b111:
+        if (!UCOP_SET(28)) {
+            disas_coproc_insn(env, s, insn);
+            break;
+        }
+        if ((insn & 0xff000000) == 0xff000000) { /* syscall */
+            gen_set_pc_im(s->pc);
+            s->is_jmp = DISAS_SYSCALL;
+            break;
+        }
+        ILLEGAL;
+    }
+
+    return;
+}
+
+/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
+   basic block 'tb'. If search_pc is TRUE, also generate PC
+   information for each intermediate instruction. */
+static inline void gen_intermediate_code_internal(CPUState *env,
+        TranslationBlock *tb, int search_pc)
+{
+    DisasContext dc1, *dc = &dc1;
+    CPUBreakpoint *bp;
+    uint16_t *gen_opc_end;
+    int j, lj;
+    target_ulong pc_start;
+    uint32_t next_page_start;
+    int num_insns;
+    int max_insns;
+
+    /* generate intermediate code */
+    num_temps = 0;
+
+    pc_start = tb->pc;
+
+    dc->tb = tb;
+
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+    dc->is_jmp = DISAS_NEXT;
+    dc->pc = pc_start;
+    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->condjmp = 0;
+    cpu_F0s = tcg_temp_new_i32();
+    cpu_F1s = tcg_temp_new_i32();
+    cpu_F0d = tcg_temp_new_i64();
+    cpu_F1d = tcg_temp_new_i64();
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    lj = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    gen_icount_start();
+    do {
+        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+                if (bp->pc == dc->pc) {
+                    gen_set_pc_im(dc->pc);
+                    gen_exception(EXCP_DEBUG);
+                    dc->is_jmp = DISAS_JUMP;
+                    /* Advance PC so that clearing the breakpoint will
+                       invalidate this TB.  */
+                    dc->pc += 2; /* FIXME */
+                    goto done_generating;
+                    break;
+                }
+            }
+        }
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = num_insns;
+        }
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        disas_uc32_insn(env, dc);
+
+        if (num_temps) {
+            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
+            num_temps = 0;
+        }
+
+        if (dc->condjmp && !dc->is_jmp) {
+            gen_set_label(dc->condlabel);
+            dc->condjmp = 0;
+        }
+        /* Translation stops when a conditional branch is encountered.
+         * Otherwise the subsequent code could get translated several times.
+         * Also stop translation when a page boundary is reached.  This
+         * ensures prefetch aborts occur at the right place.  */
+        num_insns++;
+    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
+             !env->singlestep_enabled &&
+             !singlestep &&
+             dc->pc < next_page_start &&
+             num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        if (dc->condjmp) {
+            /* FIXME:  This can theoretically happen with self-modifying
+               code.  */
+            cpu_abort(env, "IO on conditional branch instruction");
+        }
+        gen_io_end();
+    }
+
+    /* At this stage dc->condjmp will only be set when the skipped
+       instruction was a conditional branch or trap, and the PC has
+       already been written.  */
+    if (unlikely(env->singlestep_enabled)) {
+        /* Make sure the pc is updated, and raise a debug exception.  */
+        if (dc->condjmp) {
+            if (dc->is_jmp == DISAS_SYSCALL) {
+                gen_exception(UC32_EXCP_PRIV);
+            } else {
+                gen_exception(EXCP_DEBUG);
+            }
+            gen_set_label(dc->condlabel);
+        }
+        if (dc->condjmp || !dc->is_jmp) {
+            gen_set_pc_im(dc->pc);
+            dc->condjmp = 0;
+        }
+        if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) {
+            gen_exception(UC32_EXCP_PRIV);
+        } else {
+            gen_exception(EXCP_DEBUG);
+        }
+    } else {
+        /* While branches must always occur at the end of an IT block,
+           there are a few other things that can cause us to terminate
+           the TB in the middel of an IT block:
+            - Exception generating instructions (bkpt, swi, undefined).
+            - Page boundaries.
+            - Hardware watchpoints.
+           Hardware breakpoints have already been handled and skip this code.
+         */
+        switch (dc->is_jmp) {
+        case DISAS_NEXT:
+            gen_goto_tb(dc, 1, dc->pc);
+            break;
+        default:
+        case DISAS_JUMP:
+        case DISAS_UPDATE:
+            /* indicate that the hash table must be used to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_TB_JUMP:
+            /* nothing more to generate */
+            break;
+        case DISAS_SYSCALL:
+            gen_exception(UC32_EXCP_PRIV);
+            break;
+        }
+        if (dc->condjmp) {
+            gen_set_label(dc->condlabel);
+            gen_goto_tb(dc, 1, dc->pc);
+            dc->condjmp = 0;
+        }
+    }
+
+done_generating:
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("----------------\n");
+        qemu_log("IN: %s\n", lookup_symbol(pc_start));
+        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        qemu_log("\n");
+    }
+#endif
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+}
+
+void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 1);
+}
+
+static const char *cpu_mode_names[16] = {
+    "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP",
+    "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR"
+};
+
+#define UCF64_DUMP_STATE
+void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+        int flags)
+{
+    int i;
+#ifdef UCF64_DUMP_STATE
+    union {
+        uint32_t i;
+        float s;
+    } s0, s1;
+    CPU_DoubleU d;
+    /* ??? This assumes float64 and double have the same layout.
+       Oh well, it's only debug dumps.  */
+    union {
+        float64 f64;
+        double d;
+    } d0;
+#endif
+    uint32_t psr;
+
+    for (i = 0; i < 32; i++) {
+        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
+        if ((i % 4) == 3) {
+            cpu_fprintf(f, "\n");
+        } else {
+            cpu_fprintf(f, " ");
+        }
+    }
+    psr = cpu_asr_read(env);
+    cpu_fprintf(f, "PSR=%08x %c%c%c%c %s\n",
+                psr,
+                psr & (1 << 31) ? 'N' : '-',
+                psr & (1 << 30) ? 'Z' : '-',
+                psr & (1 << 29) ? 'C' : '-',
+                psr & (1 << 28) ? 'V' : '-',
+                cpu_mode_names[psr & 0xf]);
+
+#ifdef UCF64_DUMP_STATE
+    for (i = 0; i < 16; i++) {
+        d.d = env->ucf64.regs[i];
+        s0.i = d.l.lower;
+        s1.i = d.l.upper;
+        d0.f64 = d.d;
+        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%" PRIx64 "(%8g)\n",
+                    i * 2, (int)s0.i, s0.s,
+                    i * 2 + 1, (int)s1.i, s1.s,
+                    i, (uint64_t)d0.f64, d0.d);
+    }
+    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
+#endif
+}
+
+void gen_pc_load(CPUState *env, TranslationBlock *tb,
+        unsigned long searched_pc, int pc_pos, void *puc)
+{
+    env->regs[31] = gen_opc_pc[pc_pos];
+}
commit 6d76d23e82d0ce8a7874b13f5951aa763e059908
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Apr 12 00:48:33 2011 +0200

    microblaze: Add partial decoding of stream insns
    
    Based on a patch from: Alejandro Cabrera <aldaya at gmail.com>
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 1696b88..b92aa34 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -33,4 +33,7 @@ DEF_HELPER_2(mmu_write, void, i32, i32)
 
 DEF_HELPER_4(memalign, void, i32, i32, i32, i32)
 
+DEF_HELPER_2(get, i32, i32, i32)
+DEF_HELPER_3(put, void, i32, i32, i32)
+
 #include "def-helper.h"
diff --git a/target-microblaze/microblaze-decode.h b/target-microblaze/microblaze-decode.h
index 4a27476..401319e 100644
--- a/target-microblaze/microblaze-decode.h
+++ b/target-microblaze/microblaze-decode.h
@@ -50,3 +50,6 @@
 #define DEC_BR      {B8(00100110), B8(00110111)}
 #define DEC_BCC     {B8(00100111), B8(00110111)}
 #define DEC_RTS     {B8(00101101), B8(00111111)}
+
+#define DEC_STREAM  {B8(00010011), B8(00110111)}
+
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index d75a53c..39b8ec1 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -69,6 +69,41 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 }
 #endif
 
+void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
+{
+    int test = ctrl & STREAM_TEST;
+    int atomic = ctrl & STREAM_ATOMIC;
+    int control = ctrl & STREAM_CONTROL;
+    int nonblock = ctrl & STREAM_NONBLOCK;
+    int exception = ctrl & STREAM_EXCEPTION;
+
+    qemu_log("Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
+             id, data,
+             test ? "t" : "",
+             nonblock ? "n" : "",
+             exception ? "e" : "",
+             control ? "c" : "",
+             atomic ? "a" : "");
+}
+
+uint32_t helper_get(uint32_t id, uint32_t ctrl)
+{
+    int test = ctrl & STREAM_TEST;
+    int atomic = ctrl & STREAM_ATOMIC;
+    int control = ctrl & STREAM_CONTROL;
+    int nonblock = ctrl & STREAM_NONBLOCK;
+    int exception = ctrl & STREAM_EXCEPTION;
+
+    qemu_log("Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
+             id,
+             test ? "t" : "",
+             nonblock ? "n" : "",
+             exception ? "e" : "",
+             control ? "c" : "",
+             atomic ? "a" : "");
+    return 0xdead0000 | id;
+}
+
 void helper_raise_exception(uint32_t index)
 {
     env->exception_index = index;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 6f4eef1..bff3a11 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1476,6 +1476,42 @@ static void dec_null(DisasContext *dc)
     dc->abort_at_next_insn = 1;
 }
 
+/* Insns connected to FSL or AXI stream attached devices.  */
+static void dec_stream(DisasContext *dc)
+{
+    int mem_index = cpu_mmu_index(dc->env);
+    TCGv_i32 t_id, t_ctrl;
+    int ctrl;
+
+    LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
+            dc->type_b ? "" : "d", dc->imm);
+
+    if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        return;
+    }
+
+    t_id = tcg_temp_new();
+    if (dc->type_b) {
+        tcg_gen_movi_tl(t_id, dc->imm & 0xf);
+        ctrl = dc->imm >> 10;
+    } else {
+        tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
+        ctrl = dc->imm >> 5;
+    }
+
+    t_ctrl = tcg_const_tl(ctrl);
+
+    if (dc->rd == 0) {
+        gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
+    } else {
+        gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
+    }
+    tcg_temp_free(t_id);
+    tcg_temp_free(t_ctrl);
+}
+
 static struct decoder_info {
     struct {
         uint32_t bits;
@@ -1500,6 +1536,7 @@ static struct decoder_info {
     {DEC_MUL, dec_mul},
     {DEC_DIV, dec_div},
     {DEC_MSR, dec_msr},
+    {DEC_STREAM, dec_stream},
     {{0, 0}, dec_null}
 };
 
commit 8545364198da26f02f54343476947b8c11d17dfb
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Apr 12 00:42:28 2011 +0200

    microblaze: Add stream-insn related constants
    
    Based on a patch from: Alejandro Cabrera <aldaya at gmail.com>
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index d0aee19..536222e 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -79,6 +79,8 @@ struct CPUMBState;
 #define          ESR_DIZ       (1<<11) /* Zone Protection */
 #define          ESR_S         (1<<10) /* Store instruction */
 
+#define          ESR_ESS_FSL_OFFSET     5
+
 #define          ESR_EC_FSL             0
 #define          ESR_EC_UNALIGNED_DATA  1
 #define          ESR_EC_ILLEGAL_OP      2
@@ -212,6 +214,13 @@ struct CPUMBState;
 #define CC_EQ  0
 
 #define NB_MMU_MODES    3
+
+#define STREAM_EXCEPTION (1 << 0)
+#define STREAM_ATOMIC    (1 << 1)
+#define STREAM_TEST      (1 << 2)
+#define STREAM_CONTROL   (1 << 3)
+#define STREAM_NONBLOCK  (1 << 4)
+
 typedef struct CPUMBState {
     uint32_t debug;
     uint32_t btaken;
commit 2e42d52d95d613e38961727e6bac2028681340e3
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Mon Apr 11 23:57:07 2011 +0200

    microblaze: Correct ec mask in debug print
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/linux-user/main.c b/linux-user/main.c
index e651bfd..9160087 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2258,7 +2258,7 @@ void cpu_loop (CPUState *env)
                     break;
                 default:
                     printf ("Unhandled hw-exception: 0x%x\n",
-                            env->sregs[SR_ESR] & 5);
+                            env->sregs[SR_ESR] & ESR_EC_MASK);
                     cpu_dump_state(env, stderr, fprintf, 0);
                     exit (1);
                     break;
commit 3b584046aae87df3ac195cc85b89ff86c1a8db01
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Mon Apr 11 23:55:42 2011 +0200

    microblaze: Add constant for exception-code mask
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index cc09647..d0aee19 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -91,6 +91,7 @@ struct CPUMBState;
 #define          ESR_EC_INSN_STORAGE    9
 #define          ESR_EC_DATA_TLB        10
 #define          ESR_EC_INSN_TLB        11
+#define          ESR_EC_MASK            31
 
 /* Floating Point Status Register (FSR) Bits */
 #define FSR_IO          (1<<4) /* Invalid operation */
commit 7458a432f03bc9af031336af29fc6477de8c5e34
Author: Alejandro Cabrera <aldaya at gmail.com>
Date:   Mon Apr 11 23:07:58 2011 +0200

    microblaze: Correct MMU_ZONES mask
    
    Signed-off-by: Alejandro Cabrera <aldaya at gmail.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 14d4d42..cc09647 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -194,7 +194,7 @@ struct CPUMBState;
 #define PVR11_MMU_ITLB_SIZE             0x38000000
 #define PVR11_MMU_DTLB_SIZE             0x07000000
 #define PVR11_MMU_TLB_ACCESS            0x00C00000
-#define PVR11_MMU_ZONES                 0x003C0000
+#define PVR11_MMU_ZONES                 0x003E0000
 /* MSR Reset value PVR mask */
 #define PVR11_MSR_RESET_VALUE_MASK      0x000007FF
 
commit 8b2715a01e5dee434fbe070c3c855133203b2845
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 9 14:25:25 2011 +0000

    ppc: remove a write-only variable
    
    Remove a write-only variable, spotted by GCC 4.6.0:
    /src/qemu/hw/ppc.c: In function 'power7_set_irq':
    /src/qemu/hw/ppc.c:255:9: error: variable 'cur_level' set but not used [-Werror=unused-but-set-variable]
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc.c b/hw/ppc.c
index dabb816..1873328 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -252,11 +252,9 @@ void ppc970_irq_init (CPUState *env)
 static void power7_set_irq (void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
-    int cur_level;
 
     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
                 env, pin, level);
-    cur_level = (env->irq_input_state >> pin) & 1;
 
     switch (pin) {
     case POWER7_INPUT_INT:
commit 8f16753fd6b584f34d47e102d290dbf4d5c94d46
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 4 16:32:10 2011 +0200

    s390x: fix virtio feature bitmap
    
    The feature bitmap in the s390 virtio machine is little endian. To
    address for that, we need to bswap the values after reading them out.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 58af164..60e0135 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -223,7 +223,7 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
     cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
 
     /* Sync feature bitmap */
-    stl_phys(cur_offs, dev->host_features);
+    stl_phys(cur_offs, bswap32(dev->host_features));
 
     dev->feat_offs = cur_offs + dev->feat_len;
     cur_offs += dev->feat_len * 2;
@@ -246,7 +246,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
 
     /* Update guest supported feature bitmap */
 
-    features = ldl_phys(dev->feat_offs);
+    features = bswap32(ldl_phys(dev->feat_offs));
     if (vdev->set_features) {
         vdev->set_features(vdev, features);
     }
commit 7b3da903041eae8e756d5dd29c492e5f043c9954
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 4 16:32:11 2011 +0200

    s390x: set alignment for long to 8
    
    The alignment for longs on s390x is 8. That's the only place where it differs
    from the default alignments found in configure already. The example alignment
    program from Laurent printed the following on a real s390x:
    
      alignof(short) 2
      alignof(int) 4
      alignof(long) 8
      alignof(long long) 8
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 2bb3faa..a4759ae 100755
--- a/configure
+++ b/configure
@@ -3184,6 +3184,7 @@ case "$target_arch2" in
   s390x)
     target_nptl="yes"
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   *)
     echo "Unsupported target CPU"
commit d04fba948fb945e467f263e820b1100d657c533d
Author: Jan Kiszka <jan.kiszka at web.de>
Date:   Sun Apr 10 09:35:42 2011 +0200

    musicpal: Fix registration of MMIO-less sysbus devices
    
    The proper way to signal that a sysbus devices need no MMIO region is to
    pass -1 to sysbus_create_simple.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/musicpal.c b/hw/musicpal.c
index d98aa8d..52b2931 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1597,11 +1597,11 @@ static void musicpal_init(ram_addr_t ram_size,
     musicpal_misc_init();
 
     dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
-    i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
+    i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
     i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c");
 
     lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL);
-    key_dev = sysbus_create_simple("musicpal_key", 0, NULL);
+    key_dev = sysbus_create_simple("musicpal_key", -1, NULL);
 
     /* I2C read data */
     qdev_connect_gpio_out(i2c_dev, 0,
commit 23910d3f669d46073b403876e30a7314599633af
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Mar 25 19:54:41 2011 +0900

    acpi, acpi_piix: factor out GPE logic
    
    factor out ACPI GPE logic. Later it will be used by ICH9 ACPI.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi.c b/hw/acpi.c
index 2879eea..e372474 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -328,3 +328,69 @@ void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
         qemu_irq_lower(pm1_cnt->cmos_s3);
     }
 }
+
+/* ACPI GPE */
+void acpi_gpe_init(ACPIGPE *gpe, uint8_t len)
+{
+    gpe->len = len;
+    gpe->sts = qemu_mallocz(len / 2);
+    gpe->en = qemu_mallocz(len / 2);
+}
+
+void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk)
+{
+    gpe->blk = blk;
+}
+
+void acpi_gpe_reset(ACPIGPE *gpe)
+{
+    memset(gpe->sts, 0, gpe->len / 2);
+    memset(gpe->en, 0, gpe->len / 2);
+}
+
+static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
+{
+    uint8_t *cur = NULL;
+
+    if (addr < gpe->len / 2) {
+        cur = gpe->sts + addr;
+    } else if (addr < gpe->len) {
+        cur = gpe->en + addr;
+    } else {
+        abort();
+    }
+
+    return cur;
+}
+
+void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
+{
+    uint8_t *cur;
+
+    addr -= gpe->blk;
+    cur = acpi_gpe_ioport_get_ptr(gpe, addr);
+    if (addr < gpe->len / 2) {
+        /* GPE_STS */
+        *cur = (*cur) & ~val;
+    } else if (addr < gpe->len) {
+        /* GPE_EN */
+        *cur = val;
+    } else {
+        abort();
+    }
+}
+
+uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr)
+{
+    uint8_t *cur;
+    uint32_t val;
+
+    addr -= gpe->blk;
+    cur = acpi_gpe_ioport_get_ptr(gpe, addr);
+    val = 0;
+    if (cur != NULL) {
+        val = *cur;
+    }
+
+    return val;
+}
diff --git a/hw/acpi.h b/hw/acpi.h
index 836459e..c141e65 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -126,4 +126,21 @@ void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
                          bool sci_enable, bool sci_disable);
 void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt);
 
+/* GPE0 */
+struct ACPIGPE {
+    uint32_t blk;
+    uint8_t len;
+
+    uint8_t *sts;
+    uint8_t *en;
+};
+typedef struct ACPIGPE ACPIGPE;
+
+void acpi_gpe_init(ACPIGPE *gpe, uint8_t len);
+void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk);
+void acpi_gpe_reset(ACPIGPE *gpe);
+
+void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val);
+uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr);
+
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 412ace3..96f5222 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -35,17 +35,13 @@
 #define ACPI_DBG_IO_ADDR  0xb044
 
 #define GPE_BASE 0xafe0
+#define GPE_LEN 4
 #define PCI_BASE 0xae00
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 
 #define PIIX4_PCI_HOTPLUG_STATUS 2
 
-struct gpe_regs {
-    uint16_t sts; /* status */
-    uint16_t en;  /* enabled */
-};
-
 struct pci_status {
     uint32_t up;
     uint32_t down;
@@ -69,7 +65,7 @@ typedef struct PIIX4PMState {
     int kvm_enabled;
 
     /* for pci hotplug */
-    struct gpe_regs gpe;
+    ACPIGPE gpe;
     struct pci_status pci0_status;
     uint32_t pci0_hotplug_enable;
 } PIIX4PMState;
@@ -89,7 +85,7 @@ static void pm_update_sci(PIIX4PMState *s)
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
-        (((s->gpe.sts & s->gpe.en) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+        (((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
@@ -214,14 +210,25 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
     return 0;
 }
 
+#define VMSTATE_GPE_ARRAY(_field, _state)                            \
+ {                                                                   \
+     .name       = (stringify(_field)),                              \
+     .version_id = 0,                                                \
+     .num        = GPE_LEN,                                          \
+     .info       = &vmstate_info_uint16,                             \
+     .size       = sizeof(uint16_t),                                 \
+     .flags      = VMS_ARRAY | VMS_POINTER,                          \
+     .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
+ }
+
 static const VMStateDescription vmstate_gpe = {
     .name = "gpe",
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT16(sts, struct gpe_regs),
-        VMSTATE_UINT16(en, struct gpe_regs),
+        VMSTATE_GPE_ARRAY(sts, ACPIGPE),
+        VMSTATE_GPE_ARRAY(en, ACPIGPE),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -252,7 +259,7 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr.timer, PIIX4PMState),
         VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
-        VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
+        VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
         VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
                        struct pci_status),
         VMSTATE_END_OF_LIST()
@@ -346,6 +353,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
     acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
+    acpi_gpe_init(&s->gpe, GPE_LEN);
 
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
@@ -399,74 +407,20 @@ static void piix4_pm_register(void)
 
 device_init(piix4_pm_register);
 
-static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
-{
-    if (addr & 1)
-        return (val >> 8) & 0xff;
-    return val & 0xff;
-}
-
 static uint32_t gpe_readb(void *opaque, uint32_t addr)
 {
-    uint32_t val = 0;
     PIIX4PMState *s = opaque;
-    struct gpe_regs *g = &s->gpe;
-
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            val = gpe_read_val(g->sts, addr);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            val = gpe_read_val(g->en, addr);
-            break;
-        default:
-            break;
-    }
+    uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
 
     PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
     return val;
 }
 
-static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
-{
-    if (addr & 1)
-        *cur = (*cur & 0xff) | (val << 8);
-    else
-        *cur = (*cur & 0xff00) | (val & 0xff);
-}
-
-static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
-{
-    uint16_t x1, x0 = val & 0xff;
-    int shift = (addr & 1) ? 8 : 0;
-
-    x1 = (*cur >> shift) & 0xff;
-
-    x1 = x1 & ~x0;
-
-    *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
-}
-
 static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     PIIX4PMState *s = opaque;
-    struct gpe_regs *g = &s->gpe;
-
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            gpe_reset_val(&g->sts, addr, val);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            gpe_write_val(&g->en, addr, val);
-            break;
-        default:
-            break;
-    }
 
+    acpi_gpe_ioport_writeb(&s->gpe, addr, val);
     pm_update_sci(s);
 
     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
@@ -549,8 +503,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
     struct pci_status *pci0_status = &s->pci0_status;
 
-    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, s);
-    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, s);
+    register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
+    register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
+    acpi_gpe_blk(&s->gpe, GPE_BASE);
 
     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
@@ -566,13 +521,13 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 
 static void enable_device(PIIX4PMState *s, int slot)
 {
-    s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
+    s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
     s->pci0_status.up |= (1 << slot);
 }
 
 static void disable_device(PIIX4PMState *s, int slot)
 {
-    s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
+    s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
     s->pci0_status.down |= (1 << slot);
 }
 
commit be5e7a76010bd14d09f74504ed6368782e701888
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Mon Apr 4 17:38:44 2011 +0400

    arm: basic support for ARMv4/ARMv4T emulation
    
    Currently target-arm/ assumes at least ARMv5 core. Add support for
    handling also ARMv4/ARMv4T. This changes the following instructions:
    
    BX(v4T and later)
    
    BKPT, BLX, CDP2, CLZ, LDC2, LDRD, MCRR, MCRR2, MRRC, MCRR, MRC2, MRRC,
    MRRC2, PLD QADD, QDADD, QDSUB, QSUB, STRD, SMLAxy, SMLALxy, SMLAWxy,
    SMULxy, SMULWxy, STC2 (v5 and later)
    
    All instructions that are "v5TE and later" are also bound to just v5, as
    that's how it was before.
    
    This patch doesn _not_ include disabling of cp15 access and base-updated
    data abort model (that will be required to emulate chips based on a
    ARM7TDMI), because:
    * no ARM7TDMI chips are currently emulated (or planned)
    * those features aren't strictly necessary for my purposes (SA-1 core
      emulation).
    
    All v5 models are handled as they are v5T. Internally we still have a
    check if the model is a v5(T) or v5TE, but as all emulated cores are
    v5TE, those two cases are simply aliased (for now).
    
    Patch is heavily based on patch by Filip Navara <filip.navara at gmail.com>
    which in turn is based on work by Ulrich Hecht <uli at suse.de> and Vincent
    Sanders <vince at kyllikki.org>.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1ae7982..e247a7a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -360,7 +360,9 @@ enum arm_features {
     ARM_FEATURE_M, /* Microcontroller profile.  */
     ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling.  */
     ARM_FEATURE_THUMB2EE,
-    ARM_FEATURE_V7MP    /* v7 Multiprocessing Extensions */
+    ARM_FEATURE_V7MP,    /* v7 Multiprocessing Extensions */
+    ARM_FEATURE_V4T,
+    ARM_FEATURE_V5,
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6788a4c..ce9a9d8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -48,17 +48,23 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     env->cp15.c0_cpuid = id;
     switch (id) {
     case ARM_CPUID_ARM926:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
         env->cp15.c0_cachetype = 0x1dd20d2;
         env->cp15.c1_sys = 0x00090078;
         break;
     case ARM_CPUID_ARM946:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_MPU);
         env->cp15.c0_cachetype = 0x0f004006;
         env->cp15.c1_sys = 0x00000078;
         break;
     case ARM_CPUID_ARM1026:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
@@ -67,6 +73,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_ARM1136_R2:
     case ARM_CPUID_ARM1136:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
@@ -79,6 +87,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00050078;
         break;
     case ARM_CPUID_ARM11MPCORE:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
@@ -91,6 +101,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -113,6 +125,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXA9:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -140,6 +154,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c1_sys = 0x00c50078;
         break;
     case ARM_CPUID_CORTEXM3:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_V7);
@@ -147,6 +163,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -161,6 +179,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_TI915T:
     case ARM_CPUID_TI925T:
+        set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_OMAPCP);
         env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
         env->cp15.c0_cachetype = 0x5109149;
@@ -173,6 +192,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA260:
     case ARM_CPUID_PXA261:
     case ARM_CPUID_PXA262:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
         env->cp15.c0_cachetype = 0xd172172;
@@ -184,6 +205,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA270_B1:
     case ARM_CPUID_PXA270_C0:
     case ARM_CPUID_PXA270_C5:
+        set_feature(env, ARM_FEATURE_V4T);
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
         set_feature(env, ARM_FEATURE_IWMMXT);
@@ -856,7 +879,11 @@ void do_interrupt(CPUARMState *env)
     /* Switch to the new mode, and to the correct instruction set.  */
     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
     env->uncached_cpsr |= mask;
-    env->thumb = (env->cp15.c1_sys & (1 << 30)) != 0;
+    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
+     * and we should just guard the thumb mode on V4 */
+    if (arm_feature(env, ARM_FEATURE_V4T)) {
+        env->thumb = (env->cp15.c1_sys & (1 << 30)) != 0;
+    }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 55d524b..998cfd5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -34,6 +34,10 @@
 #define GEN_HELPER 1
 #include "helpers.h"
 
+#define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
+#define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
+/* currently all emulated v5 cores are also v5TE, so don't bother */
+#define ENABLE_ARCH_5TE   arm_feature(env, ARM_FEATURE_V5)
 #define ENABLE_ARCH_5J    0
 #define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
 #define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
@@ -750,6 +754,20 @@ static inline void store_reg_bx(CPUState *env, DisasContext *s,
     }
 }
 
+/* Variant of store_reg which uses branch&exchange logic when storing
+ * to r15 in ARM architecture v5T and above. This is used for storing
+ * the results of a LDR/LDM/POP into r15, and corresponds to the cases
+ * in the ARM ARM which use the LoadWritePC() pseudocode function. */
+static inline void store_reg_from_load(CPUState *env, DisasContext *s,
+                                int reg, TCGv var)
+{
+    if (reg == 15 && ENABLE_ARCH_5) {
+        gen_bx(s, var);
+    } else {
+        store_reg(s, reg, var);
+    }
+}
+
 static inline TCGv gen_ld8s(TCGv addr, int index)
 {
     TCGv tmp = tcg_temp_new_i32();
@@ -3436,6 +3454,10 @@ static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
 
     /* Mask out undefined bits.  */
     mask &= ~CPSR_RESERVED;
+    if (!arm_feature(env, ARM_FEATURE_V4T))
+        mask &= ~CPSR_T;
+    if (!arm_feature(env, ARM_FEATURE_V5))
+        mask &= ~CPSR_Q; /* V5TE in reality*/
     if (!arm_feature(env, ARM_FEATURE_V6))
         mask &= ~(CPSR_E | CPSR_GE);
     if (!arm_feature(env, ARM_FEATURE_THUMB2))
@@ -6127,6 +6149,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
         goto illegal_op;
     cond = insn >> 28;
     if (cond == 0xf){
+        /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
+         * choose to UNDEF. In ARMv5 and above the space is used
+         * for miscellaneous unconditional instructions.
+         */
+        ARCH(5);
+
         /* Unconditional instructions.  */
         if (((insn >> 25) & 7) == 1) {
             /* NEON Data processing.  */
@@ -6155,6 +6183,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 }
             }
             /* Otherwise PLD; v5TE+ */
+            ARCH(5TE);
             return;
         }
         if (((insn & 0x0f70f000) == 0x0450f000) ||
@@ -6291,6 +6320,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             val += (offset << 2) | ((insn >> 23) & 2) | 1;
             /* pipeline offset */
             val += 4;
+            /* protected by ARCH(5); above, near the start of uncond block */
             gen_bx_im(s, val);
             return;
         } else if ((insn & 0x0e000f00) == 0x0c000100) {
@@ -6302,6 +6332,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             }
         } else if ((insn & 0x0fe00000) == 0x0c400000) {
             /* Coprocessor double register transfer.  */
+            ARCH(5TE);
         } else if ((insn & 0x0f000010) == 0x0e000010) {
             /* Additional coprocessor register transfer.  */
         } else if ((insn & 0x0ff10020) == 0x01000000) {
@@ -6402,10 +6433,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
         case 0x1:
             if (op1 == 1) {
                 /* branch/exchange thumb (bx).  */
+                ARCH(4T);
                 tmp = load_reg(s, rm);
                 gen_bx(s, tmp);
             } else if (op1 == 3) {
                 /* clz */
+                ARCH(5);
                 rd = (insn >> 12) & 0xf;
                 tmp = load_reg(s, rm);
                 gen_helper_clz(tmp, tmp);
@@ -6428,6 +6461,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             if (op1 != 1)
               goto illegal_op;
 
+            ARCH(5);
             /* branch link/exchange thumb (blx) */
             tmp = load_reg(s, rm);
             tmp2 = tcg_temp_new_i32();
@@ -6436,6 +6470,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             gen_bx(s, tmp);
             break;
         case 0x5: /* saturating add/subtract */
+            ARCH(5TE);
             rd = (insn >> 12) & 0xf;
             rn = (insn >> 16) & 0xf;
             tmp = load_reg(s, rm);
@@ -6457,12 +6492,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 goto illegal_op;
             }
             /* bkpt */
+            ARCH(5);
             gen_exception_insn(s, 4, EXCP_BKPT);
             break;
         case 0x8: /* signed multiply */
         case 0xa:
         case 0xc:
         case 0xe:
+            ARCH(5TE);
             rs = (insn >> 8) & 0xf;
             rn = (insn >> 12) & 0xf;
             rd = (insn >> 16) & 0xf;
@@ -6858,6 +6895,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     }
                     load = 1;
                 } else if (sh & 2) {
+                    ARCH(5TE);
                     /* doubleword */
                     if (sh & 1) {
                         /* store */
@@ -7198,10 +7236,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             }
             if (insn & (1 << 20)) {
                 /* Complete the load.  */
-                if (rd == 15)
-                    gen_bx(s, tmp);
-                else
-                    store_reg(s, rd, tmp);
+                store_reg_from_load(env, s, rd, tmp);
             }
             break;
         case 0x08:
@@ -7254,9 +7289,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         if (insn & (1 << 20)) {
                             /* load */
                             tmp = gen_ld32(addr, IS_USER(s));
-                            if (i == 15) {
-                                gen_bx(s, tmp);
-                            } else if (user) {
+                            if (user) {
                                 tmp2 = tcg_const_i32(i);
                                 gen_helper_set_user_reg(tmp2, tmp);
                                 tcg_temp_free_i32(tmp2);
@@ -7265,7 +7298,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                                 loaded_var = tmp;
                                 loaded_base = 1;
                             } else {
-                                store_reg(s, i, tmp);
+                                store_reg_from_load(env, s, i, tmp);
                             }
                         } else {
                             /* store */
@@ -7465,6 +7498,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
            16-bit instructions to get correct prefetch abort behavior.  */
         insn = insn_hw1;
         if ((insn & (1 << 12)) == 0) {
+            ARCH(5);
             /* Second half of blx.  */
             offset = ((insn & 0x7ff) << 1);
             tmp = load_reg(s, 14);
@@ -8061,6 +8095,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 } else {
                     /* blx */
                     offset &= ~(uint32_t)2;
+                    /* thumb2 bx, no need to check */
                     gen_bx_im(s, offset);
                 }
             } else if (((insn >> 23) & 7) == 7) {
@@ -8642,11 +8677,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             case 3:/* branch [and link] exchange thumb register */
                 tmp = load_reg(s, rm);
                 if (insn & (1 << 7)) {
+                    ARCH(5);
                     val = (uint32_t)s->pc | 1;
                     tmp2 = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp2, val);
                     store_reg(s, 14, tmp2);
                 }
+                /* already thumb, no need to check */
                 gen_bx(s, tmp);
                 break;
             }
@@ -9006,8 +9043,9 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             /* write back the new stack pointer */
             store_reg(s, 13, addr);
             /* set the new PC value */
-            if ((insn & 0x0900) == 0x0900)
-                gen_bx(s, tmp);
+            if ((insn & 0x0900) == 0x0900) {
+                store_reg_from_load(env, s, 15, tmp);
+            }
             break;
 
         case 1: case 3: case 9: case 11: /* czb */
@@ -9038,6 +9076,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             break;
 
         case 0xe: /* bkpt */
+            ARCH(5);
             gen_exception_insn(s, 2, EXCP_BKPT);
             break;
 
commit 4b4a72e55660abf7efe85aca78762dcfea5519ad
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Apr 2 13:36:31 2011 +0200

    Fix conversions from pointer to tcg_target_long
    
    tcg_gen_exit_tb takes a parameter of type tcg_target_long,
    so the type casts of pointer to long should be replaced by
    type casts of pointer to tcg_target_long (suggested by Blue Swirl).
    
    These changes are needed for build environments where
    sizeof(long) != sizeof(void *), especially for w64.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/gen-icount.h b/gen-icount.h
index 8879da6..5fb3829 100644
--- a/gen-icount.h
+++ b/gen-icount.h
@@ -29,7 +29,7 @@ static void gen_icount_end(TranslationBlock *tb, int num_insns)
     if (use_icount) {
         *icount_arg = num_insns;
         gen_set_label(icount_label);
-        tcg_gen_exit_tb((long)tb + 2);
+        tcg_gen_exit_tb((tcg_target_long)tb + 2);
     }
 }
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 3a1c625..96e922b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -398,7 +398,7 @@ static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
     } else if (use_goto_tb(ctx, dest)) {
         tcg_gen_goto_tb(0);
         tcg_gen_movi_i64(cpu_pc, dest);
-        tcg_gen_exit_tb((long)ctx->tb);
+        tcg_gen_exit_tb((tcg_target_long)ctx->tb);
         return EXIT_GOTO_TB;
     } else {
         tcg_gen_movi_i64(cpu_pc, dest);
@@ -417,12 +417,12 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
 
         tcg_gen_goto_tb(0);
         tcg_gen_movi_i64(cpu_pc, ctx->pc);
-        tcg_gen_exit_tb((long)ctx->tb);
+        tcg_gen_exit_tb((tcg_target_long)ctx->tb);
 
         gen_set_label(lab_true);
         tcg_gen_goto_tb(1);
         tcg_gen_movi_i64(cpu_pc, dest);
-        tcg_gen_exit_tb((long)ctx->tb + 1);
+        tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1);
 
         return EXIT_GOTO_TB;
     } else {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index c6cb39a..55d524b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3387,7 +3387,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
         tcg_gen_goto_tb(n);
         gen_set_pc_im(dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         gen_set_pc_im(dest);
         tcg_gen_exit_tb(0);
diff --git a/target-cris/translate.c b/target-cris/translate.c
index b4648a0..1c03fa5 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -596,7 +596,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
 	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
 		tcg_gen_goto_tb(n);
 		tcg_gen_movi_tl(env_pc, dest);
-		tcg_gen_exit_tb((long)tb + n);
+                tcg_gen_exit_tb((tcg_target_long)tb + n);
 	} else {
 		tcg_gen_movi_tl(env_pc, dest);
 		tcg_gen_exit_tb(0);
diff --git a/target-i386/translate.c b/target-i386/translate.c
index c008450..7d1340e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2274,7 +2274,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
         /* jump to same page: we can use a direct jump */
         tcg_gen_goto_tb(tb_num);
         gen_jmp_im(eip);
-        tcg_gen_exit_tb((long)tb + tb_num);
+        tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
     } else {
         /* jump to another page: currently not optimized */
         gen_jmp_im(eip);
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 666d5f4..efc9b5a 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -138,7 +138,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
             likely(!dc->singlestep_enabled)) {
         tcg_gen_goto_tb(n);
         tcg_gen_movi_tl(cpu_pc, dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         tcg_gen_movi_tl(cpu_pc, dest);
         if (dc->singlestep_enabled) {
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 6f72a2b..038c0af 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -861,7 +861,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
                (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
         tcg_gen_goto_tb(n);
         tcg_gen_movi_i32(QREG_PC, dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         gen_jmp_im(s, dest);
         tcg_gen_exit_tb(0);
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index b54b169..6f4eef1 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -146,7 +146,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
         tcg_gen_goto_tb(n);
         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
         tcg_gen_exit_tb(0);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0f93e2a..953c528 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2686,7 +2686,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
         likely(!ctx->singlestep_enabled)) {
         tcg_gen_goto_tb(n);
         gen_save_pc(dest);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         gen_save_pc(dest);
         if (ctx->singlestep_enabled) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 090795b..3c3ee24 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3347,7 +3347,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
         likely(!ctx->singlestep_enabled)) {
         tcg_gen_goto_tb(n);
         tcg_gen_movi_tl(cpu_nip, dest & ~3);
-        tcg_gen_exit_tb((long)tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         tcg_gen_movi_tl(cpu_nip, dest & ~3);
         if (unlikely(ctx->singlestep_enabled)) {
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 58e9b8f..88098d7 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -302,7 +302,7 @@ static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
 	/* Use a direct jump if in same page and singlestep not enabled */
         tcg_gen_goto_tb(n);
         tcg_gen_movi_i32(cpu_pc, dest);
-        tcg_gen_exit_tb((long) tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         tcg_gen_movi_i32(cpu_pc, dest);
         if (ctx->singlestep_enabled)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index e26462e..883ecd2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -241,7 +241,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num,
         tcg_gen_goto_tb(tb_num);
         tcg_gen_movi_tl(cpu_pc, pc);
         tcg_gen_movi_tl(cpu_npc, npc);
-        tcg_gen_exit_tb((long)tb + tb_num);
+        tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
     } else {
         /* jump to another page: currently not optimized */
         tcg_gen_movi_tl(cpu_pc, pc);
commit 2caa9e9d2e0f356cc244bc41ce1d3e81663f6782
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Mon Mar 21 09:34:35 2011 +0100

    vnc: tight: Fix crash after 2GB of output
    
    fix 2Gb integer overflow in in VNC tight and zlib encodings
    
    As found by Roland Dreier <roland at purestorage.com> (excellent
    catch!), when amount of VNC compressed data produced by zlib
    and sent to client exceeds 2Gb, integer overflow occurs because
    currently, we calculate amount of data produced at each step by
    comparing saved total_out with new total_out, and total_out is
    something which grows without bounds.  Compare it with previous
    avail_out instead of total_out, and leave total_out alone.
    
    The same code is used in vnc-enc-tight.c and vnc-enc-zlib.c,
    so fix both cases.
    
    There, there's no actual need to save previous_out value, since
    capacity-offset (which is how that value is calculated) stays
    the same so it can be recalculated again after call to deflate(),
    but whole thing becomes less readable this way.
    
    Reported-by: Roland Dreier <roland at purestorage.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Corentin Chary <corentin.chary at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 2522936..87fdf35 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -868,8 +868,8 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
     zstream->avail_in = vs->tight.tight.offset;
     zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset;
     zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset;
+    previous_out = zstream->avail_out;
     zstream->data_type = Z_BINARY;
-    previous_out = zstream->total_out;
 
     /* start encoding */
     if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
@@ -878,7 +878,8 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
     }
 
     vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out;
-    bytes = zstream->total_out - previous_out;
+    /* ...how much data has actually been produced by deflate() */
+    bytes = previous_out - zstream->avail_out;
 
     tight_send_compact_size(vs, bytes);
     vnc_write(vs, vs->tight.zlib.buffer, bytes);
diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c
index 3c6e6ab..e32e4cd 100644
--- a/ui/vnc-enc-zlib.c
+++ b/ui/vnc-enc-zlib.c
@@ -103,8 +103,8 @@ static int vnc_zlib_stop(VncState *vs)
     zstream->avail_in = vs->zlib.zlib.offset;
     zstream->next_out = vs->output.buffer + vs->output.offset;
     zstream->avail_out = vs->output.capacity - vs->output.offset;
+    previous_out = zstream->avail_out;
     zstream->data_type = Z_BINARY;
-    previous_out = zstream->total_out;
 
     // start encoding
     if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
@@ -113,7 +113,7 @@ static int vnc_zlib_stop(VncState *vs)
     }
 
     vs->output.offset = vs->output.capacity - zstream->avail_out;
-    return zstream->total_out - previous_out;
+    return previous_out - zstream->avail_out;
 }
 
 int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
commit a88df0b9b517b76c1a0052fb1b0fe83080559197
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Apr 5 11:07:06 2011 +0900

    smbus_eeprom: consolidate smbus eeprom creation oc pc_piix, mips_mapta, mips_fulong
    
    consolidate smbus initialization for pc_piix, mips_malta and mips_fulong.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Cc: Huacai Chen <zltjiangshi at gmail.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 0e90d68..420fada 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -263,11 +263,9 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     qemu_irq *cpu_exit_irq;
     int via_devfn;
     PCIBus *pci_bus;
-    uint8_t *eeprom_buf;
     i2c_bus *smbus;
     int i;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DeviceState *eeprom;
     CPUState *env;
 
     /* init CPUs */
@@ -353,13 +351,8 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
 
     smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
                               0xeee1, NULL);
-    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
-    memcpy(eeprom_buf, eeprom_spd, sizeof(eeprom_spd));
     /* TODO: Populate SPD eeprom data.  */
-    eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-    qdev_prop_set_uint8(eeprom, "address", 0x50);
-    qdev_prop_set_ptr(eeprom, "data", eeprom_buf);
-    qdev_init_nofail(eeprom);
+    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
 
     /* init other devices */
     pit = pit_init(0x40, 0);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index bf0d76d..ed2a483 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -770,7 +770,6 @@ void mips_malta_init (ram_addr_t ram_size,
     qemu_irq *i8259;
     qemu_irq *cpu_exit_irq;
     int piix4_devfn;
-    uint8_t *eeprom_buf;
     i2c_bus *smbus;
     int i;
     DriveInfo *dinfo;
@@ -913,15 +912,8 @@ void mips_malta_init (ram_addr_t ram_size,
     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
                           NULL, NULL, 0);
-    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
-    for (i = 0; i < 8; i++) {
-        /* TODO: Populate SPD eeprom data.  */
-        DeviceState *eeprom;
-        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-        qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
-        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
-        qdev_init_nofail(eeprom);
-    }
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 8, NULL, 0);
     pit = pit_init(0x40, 0);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 4d54ca1..a85214b 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -37,6 +37,7 @@
 #include "sysbus.h"
 #include "arch_init.h"
 #include "blockdev.h"
+#include "smbus.h"
 
 #define MAX_IDE_BUS 2
 
@@ -154,7 +155,6 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     if (pci_enabled && acpi_enabled) {
-        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
         i2c_bus *smbus;
 
         cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
@@ -163,13 +163,7 @@ static void pc_init1(ram_addr_t ram_size,
         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                               isa_get_irq(9), *cmos_s3, *smi_irq,
                               kvm_enabled());
-        for (i = 0; i < 8; i++) {
-            DeviceState *eeprom;
-            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-            qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
-            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
-            qdev_init_nofail(eeprom);
-        }
+        smbus_eeprom_init(smbus, 8, NULL, 0);
     }
 
     if (i440fx_state) {
diff --git a/hw/smbus.h b/hw/smbus.h
index 571c52d..a398715 100644
--- a/hw/smbus.h
+++ b/hw/smbus.h
@@ -66,3 +66,6 @@ void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data
 int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data);
 void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data,
                        int len);
+
+void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
+                       const uint8_t *eeprom_spd, int size);
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 52463e0..3634754 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -96,7 +96,7 @@ static uint8_t eeprom_read_data(SMBusDevice *dev, uint8_t cmd, int n)
     return eeprom_receive_byte(dev);
 }
 
-static int smbus_eeprom_init(SMBusDevice *dev)
+static int smbus_eeprom_initfn(SMBusDevice *dev)
 {
     SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev;
 
@@ -111,7 +111,7 @@ static SMBusDeviceInfo smbus_eeprom_info = {
         DEFINE_PROP_PTR("data", SMBusEEPROMDevice, data),
         DEFINE_PROP_END_OF_LIST(),
     },
-    .init = smbus_eeprom_init,
+    .init = smbus_eeprom_initfn,
     .quick_cmd = eeprom_quick_cmd,
     .send_byte = eeprom_send_byte,
     .receive_byte = eeprom_receive_byte,
@@ -125,3 +125,21 @@ static void smbus_eeprom_register_devices(void)
 }
 
 device_init(smbus_eeprom_register_devices)
+
+void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
+                       const uint8_t *eeprom_spd, int eeprom_spd_size)
+{
+    int i;
+    uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+    if (eeprom_spd_size > 0) {
+        memcpy(eeprom_buf, eeprom_spd, eeprom_spd_size);
+    }
+
+    for (i = 0; i < nb_eeprom; i++) {
+        DeviceState *eeprom;
+        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
+        qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
+        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
+        qdev_init_nofail(eeprom);
+    }
+}
commit a0313c00fcd26530a025ff93edee32959917be8d
Author: Atsushi Nemoto <anemo at mba.ocn.ne.jp>
Date:   Tue Apr 5 23:34:04 2011 +0900

    lan9118: Ignore write to MAC_VLAN1 register
    
    On Mon, 4 Apr 2011 20:15:30 +0200, Aurelien Jarno <aurelien at aurel32.net> wrote:
    > Is it really safe ignoring write to this register? If yes, it's probably
    > a good idea to explain why in a comment. In any case, if supporting this
    > register is easy to do, it would be the best option.
    
    I think it is safe.  Please see an updated comment below.
    
    And though implementing this register might be possible, I suppose it
    is not worth to supporting FrameTooLong detection, for now at least.
    
    Thank you for comments.
    
    >8---------------------------------------------------------------------
    From: Atsushi Nemoto <anemo at mba.ocn.ne.jp>
    Date: Tue, 5 Apr 2011 23:12:07 +0900
    Subject: [PATCH] lan9118: Ignore write to MAC_VLAN1 register
    
    Since linux 2.6.38, smsc911x driver writes to VLAN1 registger.
    Since this register only affects FrameTooLong detection, ignoring
    write to this register should be safe.
    
    Signed-off-by: Atsushi Nemoto <anemo at mba.ocn.ne.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/lan9118.c b/hw/lan9118.c
index af6949f..2dc8d18 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -785,6 +785,12 @@ static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
     case MAC_FLOW:
         s->mac_flow = val & 0xffff0000;
         break;
+    case MAC_VLAN1:
+        /* Writing to this register changes a condition for
+         * FrameTooLong bit in rx_status.  Since we do not set
+         * FrameTooLong anyway, just ignore write to this.
+         */
+        break;
     default:
         hw_error("lan9118: Unimplemented MAC register write: %d = 0x%x\n",
                  s->mac_cmd & 0xf, val);
commit eaba51c573afbdd45273eed9d61d9effda979b47
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Mar 25 19:54:40 2011 +0900

    acpi, acpi_piix, vt82c686: factor out PM1_CNT logic
    
    factor out ACPI PM1_CNT logic. This will be used by ich9 acpi.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Huacai Chen <zltjiangshi at gmail.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi.c b/hw/acpi.c
index 07283be..2879eea 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -279,3 +279,52 @@ void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
     tmr->overflow_time = 0;
     qemu_del_timer(tmr->timer);
 }
+
+/* ACPI PM1aCNT */
+void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3)
+{
+    pm1_cnt->cmos_s3 = cmos_s3;
+}
+
+void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val)
+{
+    pm1_cnt->cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+
+    if (val & ACPI_BITMASK_SLEEP_ENABLE) {
+        /* change suspend type */
+        uint16_t sus_typ = (val >> 10) & 7;
+        switch(sus_typ) {
+        case 0: /* soft power off */
+            qemu_system_shutdown_request();
+            break;
+        case 1:
+            /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+               Pretend that resume was caused by power button */
+            pm1a->sts |=
+                (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
+            qemu_system_reset_request();
+            qemu_irq_raise(pm1_cnt->cmos_s3);
+        default:
+            break;
+        }
+    }
+}
+
+void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
+                         bool sci_enable, bool sci_disable)
+{
+    /* ACPI specs 3.0, 4.7.2.5 */
+    if (sci_enable) {
+        pm1_cnt->cnt |= ACPI_BITMASK_SCI_ENABLE;
+    } else if (sci_disable) {
+        pm1_cnt->cnt &= ~ACPI_BITMASK_SCI_ENABLE;
+    }
+}
+
+void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
+{
+    pm1_cnt->cnt = 0;
+    if (pm1_cnt->cmos_s3) {
+        qemu_irq_lower(pm1_cnt->cmos_s3);
+    }
+}
diff --git a/hw/acpi.h b/hw/acpi.h
index c286d7d..836459e 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -112,4 +112,18 @@ void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val);
 void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr);
 void acpi_pm1_evt_reset(ACPIPM1EVT *pm1);
 
+/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
+struct ACPIPM1CNT {
+    uint16_t cnt;
+
+    qemu_irq cmos_s3;
+};
+typedef struct ACPIPM1CNT ACPIPM1CNT;
+
+void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3);
+void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val);
+void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
+                         bool sci_enable, bool sci_disable);
+void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt);
+
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index fa7c6a9..412ace3 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -55,7 +55,7 @@ typedef struct PIIX4PMState {
     PCIDevice dev;
     IORange ioport;
     ACPIPM1EVT pm1a;
-    uint16_t pmcntrl;
+    ACPIPM1CNT pm1_cnt;
 
     APMState apm;
 
@@ -65,7 +65,6 @@ typedef struct PIIX4PMState {
     uint32_t smb_io_base;
 
     qemu_irq irq;
-    qemu_irq cmos_s3;
     qemu_irq smi_irq;
     int kvm_enabled;
 
@@ -124,30 +123,7 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
         pm_update_sci(s);
         break;
     case 0x04:
-        {
-            int sus_typ;
-            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
-            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
-                /* change suspend type */
-                sus_typ = (val >> 10) & 7;
-                switch(sus_typ) {
-                case 0: /* soft power off */
-                    qemu_system_shutdown_request();
-                    break;
-                case 1:
-                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
-                       Pretend that resume was caused by power button */
-                    s->pm1a.sts |= (ACPI_BITMASK_WAKE_STATUS |
-                                    ACPI_BITMASK_POWER_BUTTON_STATUS);
-                    qemu_system_reset_request();
-                    if (s->cmos_s3) {
-                        qemu_irq_raise(s->cmos_s3);
-                    }
-                default:
-                    break;
-                }
-            }
-        }
+        acpi_pm1_cnt_write(&s->pm1a, &s->pm1_cnt, val);
         break;
     default:
         break;
@@ -170,7 +146,7 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
         val = s->pm1a.en;
         break;
     case 0x04:
-        val = s->pmcntrl;
+        val = s->pm1_cnt.cnt;
         break;
     case 0x08:
         val = acpi_pm_tmr_get(&s->tmr);
@@ -193,11 +169,7 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
     PIIX4PMState *s = arg;
 
     /* ACPI specs 3.0, 4.7.2.5 */
-    if (val == ACPI_ENABLE) {
-        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
-    } else if (val == ACPI_DISABLE) {
-        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
-    }
+    acpi_pm1_cnt_update(&s->pm1_cnt, val == ACPI_ENABLE, val == ACPI_DISABLE);
 
     if (s->dev.config[0x5b] & (1 << 1)) {
         if (s->smi_irq) {
@@ -276,7 +248,7 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
         VMSTATE_UINT16(pm1a.sts, PIIX4PMState),
         VMSTATE_UINT16(pm1a.en, PIIX4PMState),
-        VMSTATE_UINT16(pmcntrl, PIIX4PMState),
+        VMSTATE_UINT16(pm1_cnt.cnt, PIIX4PMState),
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr.timer, PIIX4PMState),
         VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
@@ -396,7 +368,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     s = DO_UPCAST(PIIX4PMState, dev, dev);
     s->irq = sci_irq;
-    s->cmos_s3 = cmos_s3;
+    acpi_pm1_cnt_init(&s->pm1_cnt, cmos_s3);
     s->smi_irq = smi_irq;
     s->kvm_enabled = kvm_enabled;
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 10cbc74..ca8f826 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -157,7 +157,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address,
 typedef struct VT686PMState {
     PCIDevice dev;
     ACPIPM1EVT pm1a;
-    uint16_t pmcntrl;
+    ACPIPM1CNT pm1_cnt;
     APMState apm;
     ACPIPMTimer tmr;
     PMSMBus smb;
@@ -209,21 +209,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
         pm_update_sci(s);
         break;
     case 0x04:
-        {
-            int sus_typ;
-            s->pmcntrl = val & ~(SUS_EN);
-            if (val & SUS_EN) {
-                /* change suspend type */
-                sus_typ = (val >> 10) & 3;
-                switch (sus_typ) {
-                case 0: /* soft power off */
-                    qemu_system_shutdown_request();
-                    break;
-                default:
-                    break;
-                }
-            }
-        }
+        acpi_pm1_cnt_write(&s->pm1a, &s->pm1_cnt, val);
         break;
     default:
         break;
@@ -245,7 +231,7 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
         val = s->pm1a.en;
         break;
     case 0x04:
-        val = s->pmcntrl;
+        val = s->pm1_cnt.cnt;
         break;
     default:
         val = 0;
@@ -322,7 +308,7 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_PCI_DEVICE(dev, VT686PMState),
         VMSTATE_UINT16(pm1a.sts, VT686PMState),
         VMSTATE_UINT16(pm1a.en, VT686PMState),
-        VMSTATE_UINT16(pmcntrl, VT686PMState),
+        VMSTATE_UINT16(pm1_cnt.cnt, VT686PMState),
         VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr.timer, VT686PMState),
         VMSTATE_INT64(tmr.overflow_time, VT686PMState),
@@ -446,6 +432,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     apm_init(&s->apm, NULL, s);
 
     acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
+    acpi_pm1_cnt_init(&s->pm1_cnt, NULL);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 
commit 04dc308f687d45dacc664251b266b6849f5a79d0
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Mar 25 19:54:39 2011 +0900

    acpi, acpi_piix, vt82c686: factor out PM1a EVT logic
    
    factor out ACPI PM1a EVT logic.
    Later this will be used by ich9 acpi.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Huacai Chen <zltjiangshi at gmail.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi.c b/hw/acpi.c
index 08cb126..07283be 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -15,6 +15,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
+#include "sysemu.h"
 #include "hw.h"
 #include "pc.h"
 #include "acpi.h"
@@ -198,6 +199,42 @@ out:
     return -1;
 }
 
+/* ACPI PM1a EVT */
+uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time)
+{
+    int64_t d = acpi_pm_tmr_get_clock();
+    if (d >= overflow_time) {
+        pm1->sts |= ACPI_BITMASK_TIMER_STATUS;
+    }
+    return pm1->sts;
+}
+
+void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val)
+{
+    uint16_t pm1_sts = acpi_pm1_evt_get_sts(pm1, tmr->overflow_time);
+    if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
+        /* if TMRSTS is reset, then compute the new overflow time */
+        acpi_pm_tmr_calc_overflow_time(tmr);
+    }
+    pm1->sts &= ~val;
+}
+
+void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr)
+{
+    if (!pm1) {
+        qemu_system_shutdown_request();
+    } else if (pm1->en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        pm1->sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
+        tmr->update_sci(tmr);
+    }
+}
+
+void acpi_pm1_evt_reset(ACPIPM1EVT *pm1)
+{
+    pm1->sts = 0;
+    pm1->en = 0;
+}
+
 /* ACPI PM_TMR */
 void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
 {
diff --git a/hw/acpi.h b/hw/acpi.h
index fc42501..c286d7d 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -99,4 +99,17 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
                     get_ticks_per_sec());
 }
 
+/* PM1a_EVT: piix and ich9 don't implement PM1b. */
+struct ACPIPM1EVT
+{
+    uint16_t sts;
+    uint16_t en;
+};
+typedef struct ACPIPM1EVT ACPIPM1EVT;
+
+uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time);
+void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val);
+void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr);
+void acpi_pm1_evt_reset(ACPIPM1EVT *pm1);
+
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index e4ba8fc..fa7c6a9 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -54,8 +54,7 @@ struct pci_status {
 typedef struct PIIX4PMState {
     PCIDevice dev;
     IORange ioport;
-    uint16_t pmsts;
-    uint16_t pmen;
+    ACPIPM1EVT pm1a;
     uint16_t pmcntrl;
 
     APMState apm;
@@ -81,20 +80,12 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-static int get_pmsts(PIIX4PMState *s)
-{
-    int64_t d = acpi_pm_tmr_get_clock();
-    if (d >= s->tmr.overflow_time)
-        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
-    return s->pmsts;
-}
-
 static void pm_update_sci(PIIX4PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = get_pmsts(s);
-    sci_level = (((pmsts & s->pmen) &
+    pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
+    sci_level = (((pmsts & s->pm1a.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
@@ -103,7 +94,7 @@ static void pm_update_sci(PIIX4PMState *s)
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
-    acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+    acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
@@ -125,19 +116,11 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
 
     switch(addr) {
     case 0x00:
-        {
-            int pmsts;
-            pmsts = get_pmsts(s);
-            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
-                /* if TMRSTS is reset, then compute the new overflow time */
-                acpi_pm_tmr_calc_overflow_time(&s->tmr);
-            }
-            s->pmsts &= ~val;
-            pm_update_sci(s);
-        }
+        acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val);
+        pm_update_sci(s);
         break;
     case 0x02:
-        s->pmen = val;
+        s->pm1a.en = val;
         pm_update_sci(s);
         break;
     case 0x04:
@@ -154,8 +137,8 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
                 case 1:
                     /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
                        Pretend that resume was caused by power button */
-                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
-                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
+                    s->pm1a.sts |= (ACPI_BITMASK_WAKE_STATUS |
+                                    ACPI_BITMASK_POWER_BUTTON_STATUS);
                     qemu_system_reset_request();
                     if (s->cmos_s3) {
                         qemu_irq_raise(s->cmos_s3);
@@ -181,10 +164,10 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
 
     switch(addr) {
     case 0x00:
-        val = get_pmsts(s);
+        val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
         break;
     case 0x02:
-        val = s->pmen;
+        val = s->pm1a.en;
         break;
     case 0x04:
         val = s->pmcntrl;
@@ -291,8 +274,8 @@ static const VMStateDescription vmstate_acpi = {
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
-        VMSTATE_UINT16(pmsts, PIIX4PMState),
-        VMSTATE_UINT16(pmen, PIIX4PMState),
+        VMSTATE_UINT16(pm1a.sts, PIIX4PMState),
+        VMSTATE_UINT16(pm1a.en, PIIX4PMState),
         VMSTATE_UINT16(pmcntrl, PIIX4PMState),
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr.timer, PIIX4PMState),
@@ -343,13 +326,10 @@ static void piix4_reset(void *opaque)
 static void piix4_powerdown(void *opaque, int irq, int power_failing)
 {
     PIIX4PMState *s = opaque;
+    ACPIPM1EVT *pm1a = s? &s->pm1a: NULL;
+    ACPIPMTimer *tmr = s? &s->tmr: NULL;
 
-    if (!s) {
-        qemu_system_shutdown_request();
-    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
-        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
-        pm_update_sci(s);
-    }
+    acpi_pm1_evt_power_down(pm1a, tmr);
 }
 
 static int piix4_pm_initfn(PCIDevice *dev)
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 6f9c384..10cbc74 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -156,8 +156,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address,
 
 typedef struct VT686PMState {
     PCIDevice dev;
-    uint16_t pmsts;
-    uint16_t pmen;
+    ACPIPM1EVT pm1a;
     uint16_t pmcntrl;
     APMState apm;
     ACPIPMTimer tmr;
@@ -173,34 +172,19 @@ typedef struct VT686MC97State {
     PCIDevice dev;
 } VT686MC97State;
 
-#define RTC_EN    (1 << 10)
-#define PWRBTN_EN (1 << 8)
-#define GBL_EN    (1 << 5)
-#define TMROF_EN  (1 << 0)
-#define SUS_EN    (1 << 13)
-
-#define ACPI_ENABLE  0xf1
-#define ACPI_DISABLE 0xf0
-
-static int get_pmsts(VT686PMState *s)
-{
-    int64_t d = acpi_pm_tmr_get_clock();
-    if (d >= s->tmr.overflow_time) {
-        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
-    }
-    return s->pmsts;
-}
-
 static void pm_update_sci(VT686PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = get_pmsts(s);
-    sci_level = (((pmsts & s->pmen) &
-                  (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
+    pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
+    sci_level = (((pmsts & s->pm1a.en) &
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
     qemu_set_irq(s->dev.irq[0], sci_level);
     /* schedule a timer interruption if needed */
-    acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+    acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
@@ -217,19 +201,11 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     addr &= 0x0f;
     switch (addr) {
     case 0x00:
-        {
-            int pmsts;
-            pmsts = get_pmsts(s);
-            if (pmsts & val & TMROF_EN) {
-                /* if TMRSTS is reset, then compute the new overflow time */
-                acpi_pm_tmr_calc_overflow_time(&s->tmr);
-            }
-            s->pmsts &= ~val;
-            pm_update_sci(s);
-        }
+        acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val);
+        pm_update_sci(s);
         break;
     case 0x02:
-        s->pmen = val;
+        s->pm1a.en = val;
         pm_update_sci(s);
         break;
     case 0x04:
@@ -263,10 +239,10 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
     addr &= 0x0f;
     switch (addr) {
     case 0x00:
-        val = get_pmsts(s);
+        val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
         break;
     case 0x02:
-        val = s->pmen;
+        val = s->pm1a.en;
         break;
     case 0x04:
         val = s->pmcntrl;
@@ -344,8 +320,8 @@ static const VMStateDescription vmstate_acpi = {
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, VT686PMState),
-        VMSTATE_UINT16(pmsts, VT686PMState),
-        VMSTATE_UINT16(pmen, VT686PMState),
+        VMSTATE_UINT16(pm1a.sts, VT686PMState),
+        VMSTATE_UINT16(pm1a.en, VT686PMState),
         VMSTATE_UINT16(pmcntrl, VT686PMState),
         VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr.timer, VT686PMState),
commit a54d41a8b985cc7ff9d4bc52e6ca20a09216b394
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Mar 25 19:54:38 2011 +0900

    acpi, acpi_piix, vt82c686: factor out PM_TMR logic
    
    factor out PM_TMR logic. Later This will be used by ich9 acpi.
    Also fixes the same bug in vt82c686.c that was fixed by the following
    commits.
    
    > commit 055479feab63607b8042bb8ebb2e0523f17cbc4e
    > Author: aliguori <aliguori at c046a42c-6fe2-441c-8c8c-71466251a162>
    > Date:   Wed Jan 21 16:31:20 2009 +0000
    >
    >     Always return latest pmsts instead of the old one (Xiantao Zhang)
    >
    >     It may lead to the issue when booting windows guests with acpi=1
    >     if return the old pmsts.
    >
    >     Signed-off-by: Xiantao Zhang <xiantao.zhang at intel.com>
    >     Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Huacai Chen <zltjiangshi at gmail.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi.c b/hw/acpi.c
index 8071e7b..08cb126 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -197,3 +197,48 @@ out:
     }
     return -1;
 }
+
+/* ACPI PM_TMR */
+void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
+{
+    int64_t expire_time;
+
+    /* schedule a timer interruption if needed */
+    if (enable) {
+        expire_time = muldiv64(tmr->overflow_time, get_ticks_per_sec(),
+                               PM_TIMER_FREQUENCY);
+        qemu_mod_timer(tmr->timer, expire_time);
+    } else {
+        qemu_del_timer(tmr->timer);
+    }
+}
+
+void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
+{
+    int64_t d = acpi_pm_tmr_get_clock();
+    tmr->overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+}
+
+uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
+{
+    uint32_t d = acpi_pm_tmr_get_clock();;
+    return d & 0xffffff;
+}
+
+static void acpi_pm_tmr_timer(void *opaque)
+{
+    ACPIPMTimer *tmr = opaque;
+    tmr->update_sci(tmr);
+}
+
+void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci)
+{
+    tmr->update_sci = update_sci;
+    tmr->timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, tmr);
+}
+
+void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
+{
+    tmr->overflow_time = 0;
+    qemu_del_timer(tmr->timer);
+}
diff --git a/hw/acpi.h b/hw/acpi.h
index 5949958..fc42501 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -74,5 +74,29 @@
 #define ACPI_BITMASK_ARB_DISABLE                0x0001
 
 /* PM_TMR */
+struct ACPIPMTimer;
+typedef struct ACPIPMTimer ACPIPMTimer;
+
+typedef void (*acpi_update_sci_fn)(ACPIPMTimer *tmr);
+
+struct ACPIPMTimer {
+    QEMUTimer *timer;
+    int64_t overflow_time;
+
+    acpi_update_sci_fn update_sci;
+};
+
+void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable);
+void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr);
+uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr);
+void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci);
+void acpi_pm_tmr_reset(ACPIPMTimer *tmr);
+
+#include "qemu-timer.h"
+static inline int64_t acpi_pm_tmr_get_clock(void)
+{
+    return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
+                    get_ticks_per_sec());
+}
 
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 74044dd..e4ba8fc 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -60,8 +60,7 @@ typedef struct PIIX4PMState {
 
     APMState apm;
 
-    QEMUTimer *tmr_timer;
-    int64_t tmr_overflow_time;
+    ACPIPMTimer tmr;
 
     PMSMBus smb;
     uint32_t smb_io_base;
@@ -82,20 +81,10 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
-    uint32_t d;
-    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-    return d & 0xffffff;
-}
-
 static int get_pmsts(PIIX4PMState *s)
 {
-    int64_t d;
-
-    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
-                 get_ticks_per_sec());
-    if (d >= s->tmr_overflow_time)
+    int64_t d = acpi_pm_tmr_get_clock();
+    if (d >= s->tmr.overflow_time)
         s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
     return s->pmsts;
 }
@@ -103,7 +92,6 @@ static int get_pmsts(PIIX4PMState *s)
 static void pm_update_sci(PIIX4PMState *s)
 {
     int sci_level, pmsts;
-    int64_t expire_time;
 
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) &
@@ -115,19 +103,13 @@ static void pm_update_sci(PIIX4PMState *s)
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
-    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
-        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
-                               PM_TIMER_FREQUENCY);
-        qemu_mod_timer(s->tmr_timer, expire_time);
-    } else {
-        qemu_del_timer(s->tmr_timer);
-    }
+    acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+                       !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
-static void pm_tmr_timer(void *opaque)
+static void pm_tmr_timer(ACPIPMTimer *tmr)
 {
-    PIIX4PMState *s = opaque;
+    PIIX4PMState *s = container_of(tmr, PIIX4PMState, tmr);
     pm_update_sci(s);
 }
 
@@ -144,14 +126,11 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
     switch(addr) {
     case 0x00:
         {
-            int64_t d;
             int pmsts;
             pmsts = get_pmsts(s);
             if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
-                             get_ticks_per_sec());
-                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+                acpi_pm_tmr_calc_overflow_time(&s->tmr);
             }
             s->pmsts &= ~val;
             pm_update_sci(s);
@@ -211,7 +190,7 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
         val = s->pmcntrl;
         break;
     case 0x08:
-        val = get_pmtmr(s);
+        val = acpi_pm_tmr_get(&s->tmr);
         break;
     default:
         val = 0;
@@ -316,8 +295,8 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_UINT16(pmen, PIIX4PMState),
         VMSTATE_UINT16(pmcntrl, PIIX4PMState),
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
-        VMSTATE_TIMER(tmr_timer, PIIX4PMState),
-        VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
+        VMSTATE_TIMER(tmr.timer, PIIX4PMState),
+        VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
         VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
         VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
                        struct pci_status),
@@ -414,7 +393,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
-    s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
+    acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
 
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 818460d..6f9c384 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -160,8 +160,7 @@ typedef struct VT686PMState {
     uint16_t pmen;
     uint16_t pmcntrl;
     APMState apm;
-    QEMUTimer *tmr_timer;
-    int64_t tmr_overflow_time;
+    ACPIPMTimer tmr;
     PMSMBus smb;
     uint32_t smb_io_base;
 } VT686PMState;
@@ -183,45 +182,31 @@ typedef struct VT686MC97State {
 #define ACPI_ENABLE  0xf1
 #define ACPI_DISABLE 0xf0
 
-static uint32_t get_pmtmr(VT686PMState *s)
-{
-    uint32_t d;
-    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-    return d & 0xffffff;
-}
-
 static int get_pmsts(VT686PMState *s)
 {
-    int64_t d;
-    int pmsts;
-    pmsts = s->pmsts;
-    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-    if (d >= s->tmr_overflow_time)
-        s->pmsts |= TMROF_EN;
-    return pmsts;
+    int64_t d = acpi_pm_tmr_get_clock();
+    if (d >= s->tmr.overflow_time) {
+        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
+    }
+    return s->pmsts;
 }
 
 static void pm_update_sci(VT686PMState *s)
 {
     int sci_level, pmsts;
-    int64_t expire_time;
 
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) &
                   (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
     qemu_set_irq(s->dev.irq[0], sci_level);
     /* schedule a timer interruption if needed */
-    if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(), PM_TIMER_FREQUENCY);
-        qemu_mod_timer(s->tmr_timer, expire_time);
-    } else {
-        qemu_del_timer(s->tmr_timer);
-    }
+    acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+                       !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
-static void pm_tmr_timer(void *opaque)
+static void pm_tmr_timer(ACPIPMTimer *tmr)
 {
-    VT686PMState *s = opaque;
+    VT686PMState *s = container_of(tmr, VT686PMState, tmr);
     pm_update_sci(s);
 }
 
@@ -233,13 +218,11 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     switch (addr) {
     case 0x00:
         {
-            int64_t d;
             int pmsts;
             pmsts = get_pmsts(s);
             if (pmsts & val & TMROF_EN) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+                acpi_pm_tmr_calc_overflow_time(&s->tmr);
             }
             s->pmsts &= ~val;
             pm_update_sci(s);
@@ -310,7 +293,7 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     addr &= 0x0f;
     switch (addr) {
     case 0x08:
-        val = get_pmtmr(s);
+        val = acpi_pm_tmr_get(&s->tmr);
         break;
     default:
         val = 0;
@@ -365,8 +348,8 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_UINT16(pmen, VT686PMState),
         VMSTATE_UINT16(pmcntrl, VT686PMState),
         VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState),
-        VMSTATE_TIMER(tmr_timer, VT686PMState),
-        VMSTATE_INT64(tmr_overflow_time, VT686PMState),
+        VMSTATE_TIMER(tmr.timer, VT686PMState),
+        VMSTATE_INT64(tmr.overflow_time, VT686PMState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -486,7 +469,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     apm_init(&s->apm, NULL, s);
 
-    s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
+    acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 
commit 5145b3d1cc4dc77d82086d99b0690a76e1073071
Author: Jordan Justen <jordan.l.justen at intel.com>
Date:   Sun Apr 3 13:16:26 2011 -0700

    hw/pflash_cfi02: Fix lazy reset of ROMD mode
    
    When checking pfl->rom_mode for when to lazily reenter ROMD mode,
    the value was check was the opposite of what it should have been.
    This prevent the part from returning to ROMD mode after a write
    was made to the CFI rom region.
    
    Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 30c8aa4..370c5ee 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -112,7 +112,7 @@ static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset,
 
     DPRINTF("%s: offset " TARGET_FMT_plx "\n", __func__, offset);
     ret = -1;
-    if (pfl->rom_mode) {
+    if (!pfl->rom_mode) {
         /* Lazy reset of to ROMD mode */
         if (pfl->wcycle == 0)
             pflash_register_memory(pfl, 1);
commit 29e5badadffe2cc70a911a95e258d1fb01f2db71
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Apr 8 14:15:50 2011 -0500

    configure: avoid basename usage message
    
    basename prints a missing-argument error when sdlconfig is empty
    and we're cross-compiling.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/configure b/configure
index ae97e11..2bb3faa 100755
--- a/configure
+++ b/configure
@@ -1233,7 +1233,7 @@ else
   fi
   sdl=no
 fi
-if test -n "$cross_prefix" && test "`basename $sdlconfig`" = sdl-config; then
+if test -n "$cross_prefix" && test "$(basename "$sdlconfig")" = sdl-config; then
   echo warning: using "\"$sdlconfig\"" to detect cross-compiled sdl >&2
 fi
 
commit 72b310e99a5752d520af82d641c6cafa5b1058ea
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Apr 8 17:06:37 2011 -0500

    mpc85xx_pci_map_irq: change "unknow" to "unknown"
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 11edd03..2fc8792 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -198,7 +198,7 @@ static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
             ret = (irq_num + devno - 0x10) % 4;
             break;
         default:
-            printf("Error:%s:unknow dev number\n", __func__);
+            printf("Error:%s:unknown dev number\n", __func__);
     }
 
     pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
commit 97697373b41ec1d337d6826d981a0cb4e75c37f0
Author: Brad Hards <bradh at frogmouth.net>
Date:   Sat Apr 9 12:11:36 2011 +1000

    event: trivial coding style fixes
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/input.c b/input.c
index ec05548..5664d3a 100644
--- a/input.c
+++ b/input.c
@@ -161,15 +161,15 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
 
     if (mouse_event) {
         if (graphic_rotate) {
-            if (entry->qemu_put_mouse_event_absolute)
+            if (entry->qemu_put_mouse_event_absolute) {
                 width = 0x7fff;
-            else
+            } else {
                 width = graphic_width - 1;
-            mouse_event(mouse_event_opaque,
-                        width - dy, dx, dz, buttons_state);
-        } else
-            mouse_event(mouse_event_opaque,
-                        dx, dy, dz, buttons_state);
+            }
+            mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
+        } else {
+            mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
+        }
     }
 }
 
commit f95857b34d284895816f2091ef4fc6d9460ebf3b
Author: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
Date:   Fri Apr 8 08:48:42 2011 +0200

    multiboot: Quote filename in error message
    
    Quote filename in error message to spot possible whitespace character in
    the filename and make error message more meaningful.
    
    Signed-off-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index 0d2bfb4..394ed01 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -272,7 +272,7 @@ int load_multiboot(void *fw_cfg,
             mb_debug("multiboot loading module: %s\n", initrd_filename);
             mb_mod_length = get_image_size(initrd_filename);
             if (mb_mod_length < 0) {
-                fprintf(stderr, "failed to get %s image size\n", initrd_filename);
+                fprintf(stderr, "Failed to open file '%s'\n", initrd_filename);
                 exit(1);
             }
 
commit 31a44434f7b3221d911d478de3d1665bde753c86
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Apr 8 13:03:34 2011 -0600

    Add ipxe submodule
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/.gitmodules b/.gitmodules
index 44fdd1a..7884471 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
 [submodule "roms/SLOF"]
 	path = roms/SLOF
 	url = git://git.qemu.org/SLOF.git
+[submodule "roms/ipxe"]
+	path = roms/ipxe
+	url = git://git.qemu.org/ipxe.git
diff --git a/roms/ipxe b/roms/ipxe
new file mode 160000
index 0000000..7aee315
--- /dev/null
+++ b/roms/ipxe
@@ -0,0 +1 @@
+Subproject commit 7aee315f61aaf1be6d2fff26339f28a1137231a5
commit 6957785773e8a3cc8bd51f0e3172eaccbbaa5f3a
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 8 20:08:25 2011 +1000

    ppce500_mpc8544ds: Fix compile with --enable-debug and --disable-kvm
    
    When configured with --enable-debug, we compile without optimization.
    This means that the function mpc8544_copy_soc_cell() in ppce500_mpc8544ds.c
    is not optimized out, even though it is never called without kvm.  That in
    turn causes a link failure, because it calls the function
    kvmppc_read_host_property() which is in kvm_ppc.o and therefore not
    included in a --disable-kvm build.
    
    This patch fixes the problem by providing a dummy stub for
    kvmppc_read_host_property() in kvm_ppc.h when !CONFIG_KVM.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 5afb308..45a1373 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -11,8 +11,17 @@
 
 void kvmppc_init(void);
 void kvmppc_fdt_update(void *fdt);
+#ifndef CONFIG_KVM
+static inline int kvmppc_read_host_property(const char *node_path, const char *prop,
+                                            void *val, size_t len)
+{
+    assert(0);
+    return -ENOSYS;
+}
+#else
 int kvmppc_read_host_property(const char *node_path, const char *prop,
                                      void *val, size_t len);
+#endif
 
 uint32_t kvmppc_get_tbfreq(void);
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
commit 3601ff11732160e42d3174d2821d873cfcd52a59
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Apr 5 15:12:11 2011 +1000

    Use existing helper function to implement popcntd instruction
    
    The recent patches adding partial support for POWER7 cpu emulation included
    implementing the popcntd instruction.  The support for this was open coded,
    but host-utils.h already included a function implementing an equivalent
    population count function, which uses a gcc builtin (which can use special
    host instructions) if available.
    
    This patch makes the popcntd implementation use the existing, potentially
    faster, implementation.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index b1b883d..5882bec 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -528,19 +528,7 @@ target_ulong helper_popcntw (target_ulong val)
 
 target_ulong helper_popcntd (target_ulong val)
 {
-    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
-                                           0x5555555555555555ULL);
-    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
-                                           0x3333333333333333ULL);
-    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
-                                           0x0f0f0f0f0f0f0f0fULL);
-    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
-                                           0x00ff00ff00ff00ffULL);
-    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
-                                           0x0000ffff0000ffffULL);
-    val = (val & 0x00000000ffffffffULL) + ((val >> 32) &
-                                           0x00000000ffffffffULL);
-    return val;
+    return ctpop64(val);
 }
 #else
 target_ulong helper_popcntb (target_ulong val)
commit a3467baa88c5bbb58834952980d2f2206aab4445
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Apr 5 15:12:10 2011 +1000

    Delay creation of pseries device tree until reset
    
    At present, the 'pseries' machine creates a flattened device tree in the
    machine->init function to pass to either the guest kernel or to firmware.
    
    However, the machine->init function runs before processing of -device
    command line options, which means that the device tree so created will
    be (incorrectly) missing devices specified that way.
    
    Supplying a correct device tree is, in any case, part of the required
    platform entry conditions.  Therefore, this patch moves the creation and
    loading of the device tree from machine->init to a reset callback.  The
    setup of entry point address and initial register state moves with it,
    which leads to a slight cleanup.
    
    This is not, alas, quite enough to make a fully working reset for pseries.
    For that we would need to reload the firmware images, which on this
    machine are loaded into RAM.  It's a step in the right direction, though.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index f80873c..1782cc0 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -56,20 +56,16 @@
 
 sPAPREnvironment *spapr;
 
-static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
-                              const char *cpu_model,
-                              sPAPREnvironment *spapr,
-                              target_phys_addr_t initrd_base,
-                              target_phys_addr_t initrd_size,
-                              const char *boot_device,
-                              const char *kernel_cmdline,
-                              target_phys_addr_t rtas_addr,
-                              target_phys_addr_t rtas_size,
-                              long hash_shift)
+static void *spapr_create_fdt_skel(const char *cpu_model,
+                                   target_phys_addr_t initrd_base,
+                                   target_phys_addr_t initrd_size,
+                                   const char *boot_device,
+                                   const char *kernel_cmdline,
+                                   long hash_shift)
 {
     void *fdt;
     CPUState *env;
-    uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) };
+    uint64_t mem_reg_property[] = { 0, cpu_to_be64(ram_size) };
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
@@ -78,7 +74,6 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
-    int ret;
 
 #define _FDT(exp) \
     do { \
@@ -222,8 +217,21 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     _FDT((fdt_end_node(fdt))); /* close root node */
     _FDT((fdt_finish(fdt)));
 
-    /* re-expand to allow for further tweaks */
-    _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
+    return fdt;
+}
+
+static void spapr_finalize_fdt(sPAPREnvironment *spapr,
+                               target_phys_addr_t fdt_addr,
+                               target_phys_addr_t rtas_addr,
+                               target_phys_addr_t rtas_size)
+{
+    int ret;
+    void *fdt;
+
+    fdt = qemu_malloc(FDT_MAX_SIZE);
+
+    /* open out the base tree into a temp buffer for the final tweaks */
+    _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
 
     ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
     if (ret < 0) {
@@ -239,9 +247,9 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
     _FDT((fdt_pack(fdt)));
 
-    *fdt_size = fdt_totalsize(fdt);
+    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
 
-    return fdt;
+    qemu_free(fdt);
 }
 
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
@@ -254,6 +262,27 @@ static void emulate_spapr_hypercall(CPUState *env)
     env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
 }
 
+static void spapr_reset(void *opaque)
+{
+    sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
+
+    fprintf(stderr, "sPAPR reset\n");
+
+    /* flush out the hash table */
+    memset(spapr->htab, 0, spapr->htab_size);
+
+    /* Load the fdt */
+    spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
+                       spapr->rtas_size);
+
+    /* Set up the entry state */
+    first_cpu->gpr[3] = spapr->fdt_addr;
+    first_cpu->gpr[5] = 0;
+    first_cpu->halted = 0;
+    first_cpu->nip = spapr->entry_point;
+
+}
+
 /* pSeries LPAR / sPAPR hardware init */
 static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *boot_device,
@@ -262,15 +291,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
-    void *fdt, *htab;
     CPUState *env;
     int i;
     ram_addr_t ram_offset;
-    target_phys_addr_t fdt_addr, rtas_addr;
-    uint32_t kernel_base, initrd_base;
-    long kernel_size, initrd_size, htab_size, rtas_size, fw_size;
+    uint32_t initrd_base;
+    long kernel_size, initrd_size, fw_size;
     long pteg_shift = 17;
-    int fdt_size;
     char *filename;
     int irq = 16;
 
@@ -280,9 +306,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     /* We place the device tree just below either the top of RAM, or
      * 2GB, so that it can be processed with 32-bit code if
      * necessary */
-    fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
-    /* RTAS goes just below that */
-    rtas_addr = fdt_addr - RTAS_MAX_SIZE;
+    spapr->fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
+    spapr->rtas_addr = spapr->fdt_addr - RTAS_MAX_SIZE;
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -311,18 +336,19 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     /* allocate hash page table.  For now we always make this 16mb,
      * later we should probably make it scale to the size of guest
      * RAM */
-    htab_size = 1ULL << (pteg_shift + 7);
-    htab = qemu_mallocz(htab_size);
+    spapr->htab_size = 1ULL << (pteg_shift + 7);
+    spapr->htab = qemu_malloc(spapr->htab_size);
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        env->external_htab = htab;
+        env->external_htab = spapr->htab;
         env->htab_base = -1;
-        env->htab_mask = htab_size - 1;
+        env->htab_mask = spapr->htab_size - 1;
     }
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
-    rtas_size = load_image_targphys(filename, rtas_addr, ram_size - rtas_addr);
-    if (rtas_size < 0) {
+    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
+                                           ram_size - spapr->rtas_addr);
+    if (spapr->rtas_size < 0) {
         hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
         exit(1);
     }
@@ -368,13 +394,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     if (kernel_filename) {
         uint64_t lowaddr = 0;
 
-        kernel_base = KERNEL_LOAD_ADDR;
-
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename, kernel_base,
-                                              ram_size - kernel_base);
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
         }
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
@@ -396,6 +421,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
             initrd_base = 0;
             initrd_size = 0;
         }
+
+        spapr->entry_point = KERNEL_LOAD_ADDR;
     } else {
         if (ram_size < (MIN_RAM_SLOF << 20)) {
             fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
@@ -409,7 +436,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
             exit(1);
         }
         qemu_free(filename);
-        kernel_base = 0x100;
+        spapr->entry_point = 0x100;
         initrd_base = 0;
         initrd_size = 0;
 
@@ -421,20 +448,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* Prepare the device tree */
-    fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, spapr,
-                           initrd_base, initrd_size,
-                           boot_device, kernel_cmdline,
-                           rtas_addr, rtas_size, pteg_shift + 7);
-    assert(fdt != NULL);
+    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
+                                            initrd_base, initrd_size,
+                                            boot_device, kernel_cmdline,
+                                            pteg_shift + 7);
+    assert(spapr->fdt_skel != NULL);
 
-    cpu_physical_memory_write(fdt_addr, fdt, fdt_size);
-
-    qemu_free(fdt);
-
-    first_cpu->gpr[3] = fdt_addr;
-    first_cpu->gpr[5] = 0;
-    first_cpu->hreset_vector = kernel_base;
-    first_cpu->halted = 0;
+    qemu_register_reset(spapr_reset, spapr);
 }
 
 static QEMUMachine spapr_machine = {
diff --git a/hw/spapr.h b/hw/spapr.h
index fae8e13..b52133a 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -7,6 +7,13 @@ struct icp_state;
 typedef struct sPAPREnvironment {
     struct VIOsPAPRBus *vio_bus;
     struct icp_state *icp;
+
+    void *htab;
+    long htab_size;
+    target_phys_addr_t fdt_addr, rtas_addr;
+    long rtas_size;
+    void *fdt_skel;
+    target_ulong entry_point;
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
commit c7a5c0c9280c2ddaa875e3cafb3df16a96af809c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Apr 5 15:12:09 2011 +1000

    pseries: Abolish envs array
    
    Currently the pseries machine init code builds up an array, envs, of
    CPUState pointers for all the cpus in the system.  This is kind of
    pointless, given the generic code already has a perfectly good linked list
    of the cpus.
    
    In addition, there are a number of places which assume that the cpu's
    cpu_index field is equal to its index in this array.  This is true in
    practice, because cpu_index values are just assigned sequentially, but
    it's conceptually incorrect and may not always be true.
    
    Therefore, this patch abolishes the envs array, and explicitly uses the
    generic cpu linked list and cpu_index values throughout.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 1152a25..f80873c 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -57,7 +57,7 @@
 sPAPREnvironment *spapr;
 
 static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
-                              const char *cpu_model, CPUState *envs[],
+                              const char *cpu_model,
                               sPAPREnvironment *spapr,
                               target_phys_addr_t initrd_base,
                               target_phys_addr_t initrd_size,
@@ -68,6 +68,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                               long hash_shift)
 {
     void *fdt;
+    CPUState *env;
     uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) };
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
@@ -135,14 +136,14 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
         modelname[i] = toupper(modelname[i]);
     }
 
-    for (i = 0; i < smp_cpus; i++) {
-        CPUState *env = envs[i];
-        uint32_t gserver_prop[] = {cpu_to_be32(i), 0}; /* HACK! */
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        int index = env->cpu_index;
+        uint32_t gserver_prop[] = {cpu_to_be32(index), 0}; /* HACK! */
         char *nodename;
         uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                            0xffffffff, 0xffffffff};
 
-        if (asprintf(&nodename, "%s@%x", modelname, i) < 0) {
+        if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {
             fprintf(stderr, "Allocation failure\n");
             exit(1);
         }
@@ -151,7 +152,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
         free(nodename);
 
-        _FDT((fdt_property_cell(fdt, "reg", i)));
+        _FDT((fdt_property_cell(fdt, "reg", index)));
         _FDT((fdt_property_string(fdt, "device_type", "cpu")));
 
         _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
@@ -168,11 +169,11 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                            pft_size_prop, sizeof(pft_size_prop))));
         _FDT((fdt_property_string(fdt, "status", "okay")));
         _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
-        _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", i)));
+        _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", index)));
         _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
                            gserver_prop, sizeof(gserver_prop))));
 
-        if (envs[i]->mmu_model & POWERPC_MMU_1TSEG) {
+        if (env->mmu_model & POWERPC_MMU_1TSEG) {
             _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
                                segs, sizeof(segs))));
         }
@@ -261,8 +262,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
-    CPUState *envs[MAX_CPUS];
     void *fdt, *htab;
+    CPUState *env;
     int i;
     ram_addr_t ram_offset;
     target_phys_addr_t fdt_addr, rtas_addr;
@@ -288,7 +289,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         cpu_model = "POWER7";
     }
     for (i = 0; i < smp_cpus; i++) {
-        CPUState *env = cpu_init(cpu_model);
+        env = cpu_init(cpu_model);
 
         if (!env) {
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
@@ -300,9 +301,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
         env->hreset_vector = 0x60;
         env->hreset_excp_prefix = 0;
-        env->gpr[3] = i;
-
-        envs[i] = env;
+        env->gpr[3] = env->cpu_index;
     }
 
     /* allocate RAM */
@@ -315,10 +314,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     htab_size = 1ULL << (pteg_shift + 7);
     htab = qemu_mallocz(htab_size);
 
-    for (i = 0; i < smp_cpus; i++) {
-        envs[i]->external_htab = htab;
-        envs[i]->htab_base = -1;
-        envs[i]->htab_mask = htab_size - 1;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        env->external_htab = htab;
+        env->htab_base = -1;
+        env->htab_mask = htab_size - 1;
     }
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
@@ -330,7 +329,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     qemu_free(filename);
 
     /* Set up Interrupt Controller */
-    spapr->icp = xics_system_init(smp_cpus, envs, XICS_IRQS);
+    spapr->icp = xics_system_init(XICS_IRQS);
 
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
@@ -416,13 +415,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
         /* SLOF will startup the secondary CPUs using RTAS,
            rather than expecting a kexec() style entry */
-        for (i = 0; i < smp_cpus; i++) {
-            envs[i]->halted = 1;
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            env->halted = 1;
         }
     }
 
     /* Prepare the device tree */
-    fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
+    fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, spapr,
                            initrd_base, initrd_size,
                            boot_device, kernel_cmdline,
                            rtas_addr, rtas_size, pteg_shift + 7);
@@ -432,10 +431,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     qemu_free(fdt);
 
-    envs[0]->gpr[3] = fdt_addr;
-    envs[0]->gpr[5] = 0;
-    envs[0]->hreset_vector = kernel_base;
-    envs[0]->halted = 0;
+    first_cpu->gpr[3] = fdt_addr;
+    first_cpu->gpr[5] = 0;
+    first_cpu->hreset_vector = kernel_base;
+    first_cpu->halted = 0;
 }
 
 static QEMUMachine spapr_machine = {
diff --git a/hw/xics.c b/hw/xics.c
index 66047a6..13a1d25 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -425,27 +425,39 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
     rtas_st(rets, 0, 0); /* Success */
 }
 
-struct icp_state *xics_system_init(int nr_servers, CPUState *servers[],
-                                   int nr_irqs)
+struct icp_state *xics_system_init(int nr_irqs)
 {
+    CPUState *env;
+    int max_server_num;
     int i;
     struct icp_state *icp;
     struct ics_state *ics;
 
+    max_server_num = -1;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        if (env->cpu_index > max_server_num) {
+            max_server_num = env->cpu_index;
+        }
+    }
+
     icp = qemu_mallocz(sizeof(*icp));
-    icp->nr_servers = nr_servers;
-    icp->ss = qemu_mallocz(nr_servers * sizeof(struct icp_server_state));
+    icp->nr_servers = max_server_num + 1;
+    icp->ss = qemu_mallocz(icp->nr_servers*sizeof(struct icp_server_state));
+
+    for (i = 0; i < icp->nr_servers; i++) {
+        icp->ss[i].mfrr = 0xff;
+    }
 
-    for (i = 0; i < nr_servers; i++) {
-        servers[i]->cpu_index = i;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        struct icp_server_state *ss = &icp->ss[env->cpu_index];
 
-        switch (PPC_INPUT(servers[i])) {
+        switch (PPC_INPUT(env)) {
         case PPC_FLAGS_INPUT_POWER7:
-            icp->ss[i].output = servers[i]->irq_inputs[POWER7_INPUT_INT];
+            ss->output = env->irq_inputs[POWER7_INPUT_INT];
             break;
 
         case PPC_FLAGS_INPUT_970:
-            icp->ss[i].output = servers[i]->irq_inputs[PPC970_INPUT_INT];
+            ss->output = env->irq_inputs[PPC970_INPUT_INT];
             break;
 
         default:
@@ -453,8 +465,6 @@ struct icp_state *xics_system_init(int nr_servers, CPUState *servers[],
                      "model\n");
             exit(1);
         }
-
-        icp->ss[i].mfrr = 0xff;
     }
 
     ics = qemu_mallocz(sizeof(*ics));
diff --git a/hw/xics.h b/hw/xics.h
index 096eeb3..83c1182 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -33,7 +33,6 @@ struct icp_state;
 
 qemu_irq xics_find_qirq(struct icp_state *icp, int irq);
 
-struct icp_state *xics_system_init(int nr_servers, CPUState *servers[],
-                                   int nr_irqs);
+struct icp_state *xics_system_init(int nr_irqs);
 
 #endif /* __XICS_H__ */
commit 8804f57b531e4887ad9521c9abb9e0bbbcb1dd4e
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 3 18:21:24 2011 +0200

    spapr_vscsi: Set uninitialized variable
    
    cppcheck reports this error:
    
    hw/spapr_vscsi.c:274: error: Uninitialized variable: rc
    
    If llen == 0, rc was indeed used without being initialized.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index e142dae..9928334 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -255,7 +255,7 @@ static int vscsi_srp_direct_data(VSCSIState *s, vscsi_req *req,
 {
     struct srp_direct_buf *md = req->cur_desc;
     uint32_t llen;
-    int rc;
+    int rc = 0;
 
     dprintf("VSCSI: direct segment 0x%x bytes, va=0x%llx desc len=0x%x\n",
             len, (unsigned long long)md->va, md->len);
commit 64a4d100b502f24d0116437b9e5678c032a233e6
Author: Scott Wood <scottwood at freescale.com>
Date:   Mon Oct 4 11:15:58 2010 +0000

    Don't call cpu_synchronize_state() from machine init.
    
    This will deadlock when the I/O thread is used, since the
    CPU thread is blocked waiting for qemu_system_ready.
    
    The synchronization is unnecessary since this is before
    cpu_synchronize_all_post_init().
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 34ddf45..645e84f 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -156,8 +156,6 @@ static void bamboo_init(ram_addr_t ram_size,
             exit(1);
         }
 
-        cpu_synchronize_state(env);
-
         /* Set initial guest state. */
         env->gpr[1] = (16<<20) - 8;
         env->gpr[3] = FDT_ADDR;
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index b7670ae..e111dda 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -268,8 +268,6 @@ static void mpc8544ds_init(ram_addr_t ram_size,
             exit(1);
         }
 
-        cpu_synchronize_state(env);
-
         /* Set initial guest state. */
         env->gpr[1] = (16<<20) - 8;
         env->gpr[3] = dt_base;
commit f124a410ea12a644c3577c5303846c37baa5e819
Merge: e54f177... 52c0502...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 7 09:56:09 2011 -0500

    Merge remote branch 'kwolf/for-anthony' into staging

commit 52c050236eaa4f0b5e1d160cd66dc18106445c4d
Author: Christoph Hellwig <hch at lst.de>
Date:   Wed Apr 6 20:28:34 2011 +0200

    virtio-blk: fail unaligned requests
    
    Like all block drivers virtio-blk should not allow small than block size
    granularity access.  But given that the protocol specifies a
    byte unit length field we currently accept such requests, which cause
    qemu to abort() in lower layers.  Add checks to the main read and
    write handlers to catch them early.
    
    Reported-by: Conor Murphy <conor_murphy_virt at hotmail.com>
    Tested-by: Conor Murphy <conor_murphy_virt at hotmail.com>
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index b14fb99..91e0394 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -290,6 +290,10 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
+    if (req->qiov.size % req->dev->conf->logical_block_size) {
+        virtio_blk_rw_complete(req, -EIO);
+        return;
+    }
 
     if (mrb->num_writes == 32) {
         virtio_submit_multiwrite(req->dev->bs, mrb);
@@ -317,6 +321,10 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
+    if (req->qiov.size % req->dev->conf->logical_block_size) {
+        virtio_blk_rw_complete(req, -EIO);
+        return;
+    }
 
     acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
                          req->qiov.size / BDRV_SECTOR_SIZE,
commit e54f17713f638189e79dac5ba0aa0ce606788777
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Thu Apr 7 13:02:04 2011 +1000

    virtio-balloon: fixed endianness bug in the config space
    
    The specification for the virtio balloon device requres that the values
    in the config space be encoded little-endian.  This differs from most
    virtio things, where guest-native endian is the norm.
    
    Currently, the qemu virtio-balloon code correctly makes the conversion
    on get_config(), but doesn't on set_config for the 'actual' field.  The
    kernel driver, on the other hand, correctly converts when setting the
    actual field, but does not convert when reading the config space.  The
    upshot is that virtio-balloon will only work correctly if both host and
    guest are LE, making all the conversions nops.
    
    This patch corrects the qemu side, correctly doing host-native <-> LE
    conversions when accessing the config space.  This won't break any setups
    that aren't already broken, and fixes the case of BE host, LE guest.
    Fixing the BE guest case will require kernel fixes as well.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 8adddea..257baf8 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -191,7 +191,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
     VirtIOBalloon *dev = to_virtio_balloon(vdev);
     struct virtio_balloon_config config;
     memcpy(&config, config_data, 8);
-    dev->actual = config.actual;
+    dev->actual = le32_to_cpu(config.actual);
 }
 
 static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
commit 4e37bfc1f0fcd17e48bfae233e0b45066830e126
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Thu Apr 7 13:02:03 2011 +1000

    virtio-9p: fixed LE-to-host conversion bug when QEMU is called from guest
    
    The 9p code already contains an attempt at the necessary endian
    conversions, but it's broken.
    
    The code which does conversion from host to guest does it correctly
    and this code was copied to the function which does guest to host
    conversion.  However the copied code hasn't been correctly updated, so
    it first endian converts some garbage on the stack and then overwrites
    it with a field from incoming packet without conversion.
    
    The patch fixes the mistakes.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7c59988..7e29535 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -696,25 +696,22 @@ static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
         case 'w': {
             uint16_t val, *valp;
             valp = va_arg(ap, uint16_t *);
-            val = le16_to_cpupu(valp);
             offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = val;
+            *valp = le16_to_cpu(val);
             break;
         }
         case 'd': {
             uint32_t val, *valp;
             valp = va_arg(ap, uint32_t *);
-            val = le32_to_cpupu(valp);
             offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = val;
+            *valp = le32_to_cpu(val);
             break;
         }
         case 'q': {
             uint64_t val, *valp;
             valp = va_arg(ap, uint64_t *);
-            val = le64_to_cpup(valp);
             offset += pdu_unpack(&val, pdu, offset, sizeof(val));
-            *valp = val;
+            *valp = le64_to_cpu(val);
             break;
         }
         case 'v': {
commit fa227023f044552ec48ca851411dba2f268a912c
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Thu Apr 7 13:02:02 2011 +1000

    spapr_llan: Fix warning when compiled with -dDEBUG
    
    Compiling with the DEBUG macro causes leaves hw/spapr_llan.c with an
    unused variable, which is treated as an error in the qemu build.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 1d83fd5..ff3a78f 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -274,9 +274,6 @@ static target_ulong h_register_logical_lan(CPUState *env,
     VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
     VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
     vlan_bd_t filter_list_bd;
-#ifdef DEBUG
-    target_ulong mac_address = args[4];
-#endif
 
     if (!dev) {
         return H_PARAMETER;
commit 3b29a1018457875a983bf10667cfe3a80c9d6dfd
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Wed Apr 6 17:51:59 2011 +0400

    qdev: Fix comment around qdev_init_nofail()
    
    In previous life qdev_init_nofail() used to call hw_error() which
    did register dump and other scary things.  Now it calls
    error_report() and does a regular exit(1).  Fix the comment
    to match reality.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 1aa1ea0..9519f5d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -358,7 +358,8 @@ int qdev_simple_unplug_cb(DeviceState *dev)
     return 0;
 }
 
-/* Like qdev_init(), but terminate program via hw_error() instead of
+
+/* Like qdev_init(), but terminate program via error_report() instead of
    returning an error value.  This is okay during machine creation.
    Don't use for hotplug, because there callers need to recover from
    failure.  Exception: if you know the device's init() callback can't
commit 62a2ab6aed53f30080c4151044c90945d16ac5fd
Author: Brad Hards <bradh at frogmouth.net>
Date:   Tue Apr 5 07:54:04 2011 +1000

    usb-ccid: Spelling fixes
    
    While looking at David Gibson's build-fix for hw/usb-ccid.c, I noticed a spello
    in a comment on the following (unchanged) line.
    
    Signed-off-by: Brad Hards <bradh at frogmouth.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 44156cc..079b4a2 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -22,7 +22,7 @@
  *  "Universal Serial Bus, Device Class: Smart Card"
  *  Specification for Integrated Circuit(s) Cards Interface Devices
  *
- * Endianess note: from the spec (1.3)
+ * Endianness note: from the spec (1.3)
  *  "Fields that are larger than a byte are stored in little endian"
  *
  * KNOWN BUGS
@@ -172,7 +172,7 @@ enum {
     CLOCK_STATUS_RUNNING = 0,
     /*
      * 0 - Clock Running, 1 - Clock stopped in State L, 2 - H,
-     * 3 - unkonwn state. rest are RFU
+     * 3 - unknown state. rest are RFU
      */
 };
 
@@ -1200,7 +1200,7 @@ void ccid_card_card_error(CCIDCardState *card, uint64_t error)
     s->bmCommandStatus = COMMAND_STATUS_FAILED;
     s->last_answer_error = error;
     DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
-    /* TODO: these error's should be more verbose and propogated to the guest.*/
+    /* TODO: these errors should be more verbose and propagated to the guest.*/
     /*
      * We flush all pending answers on CardRemove message in ccid-card-passthru,
      * so check that first to not trigger abort
@@ -1319,7 +1319,7 @@ static void ccid_pre_save(void *opaque)
     if (s->dev.attached) {
         /*
          * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
-         * erronous detach.
+         * erroneous detach.
          */
         s->migration_state = MIGRATION_MIGRATED;
     }
commit 155eb9aa09249874b4ff49e94c58595ad82d3abb
Author: Avishay Traeger <AVISHAY at il.ibm.com>
Date:   Wed Apr 6 10:45:36 2011 +0300

    Fix integer overflow in block migration bandwidth calculation
    
    block_mig_state.reads is an int, and multiplying by BLOCK_SIZE yielded a
    negative number, resulting in a negative bandwidth (running on a 32-bit
    machine).  Change order to avoid.
    
    Signed-off-by: Avishay Traeger <avishay at il.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 8218bac..576e55a 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -140,7 +140,7 @@ static inline void add_avg_read_time(int64_t time)
 static inline long double compute_read_bwidth(void)
 {
     assert(block_mig_state.total_time != 0);
-    return  (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time;
+    return (block_mig_state.reads / block_mig_state.total_time) * BLOCK_SIZE;
 }
 
 static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
commit 7d905f716bea633f2836e1d661387983aacdc6d6
Author: Jason Wang <jasowang at redhat.com>
Date:   Wed Apr 6 18:34:31 2011 +0800

    floppy: save and restore DIR register
    
    We need to keep DIR register unchanged across migration, but currently it
    depends on the media_changed flags from block layer. Since we do not
    save/restore it and the bdrv_open() called in dest node may set the
    media_changed flag when trying to open floppy image, guest driver may think the
    floppy have changed after migration. To fix this, a new filed media_changed in
    FDrive strcutre was introduced in order to save and restore the it from block
    layer through pre_save/post_load callbacks.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 9fdbc75..edf0360 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -36,6 +36,7 @@
 #include "qdev-addr.h"
 #include "blockdev.h"
 #include "sysemu.h"
+#include "block_int.h"
 
 /********************************************************/
 /* debug Floppy devices */
@@ -82,6 +83,7 @@ typedef struct FDrive {
     uint8_t max_track;        /* Nb of tracks           */
     uint16_t bps;             /* Bytes per sector       */
     uint8_t ro;               /* Is read-only           */
+    uint8_t media_changed;    /* Is media changed       */
 } FDrive;
 
 static void fd_init(FDrive *drv)
@@ -533,16 +535,63 @@ static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
     NULL,
 };
 
+static void fdrive_media_changed_pre_save(void *opaque)
+{
+    FDrive *drive = opaque;
+
+    drive->media_changed = drive->bs->media_changed;
+}
+
+static int fdrive_media_changed_post_load(void *opaque, int version_id)
+{
+    FDrive *drive = opaque;
+
+    if (drive->bs != NULL) {
+        drive->bs->media_changed = drive->media_changed;
+    }
+
+    /* User ejected the floppy when drive->bs == NULL */
+    return 0;
+}
+
+static bool fdrive_media_changed_needed(void *opaque)
+{
+    FDrive *drive = opaque;
+
+    return (drive->bs != NULL && drive->bs->media_changed != 1);
+}
+
+static const VMStateDescription vmstate_fdrive_media_changed = {
+    .name = "fdrive/media_changed",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = fdrive_media_changed_pre_save,
+    .post_load = fdrive_media_changed_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(media_changed, FDrive),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_fdrive = {
     .name = "fdrive",
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
+    .fields      = (VMStateField[]) {
         VMSTATE_UINT8(head, FDrive),
         VMSTATE_UINT8(track, FDrive),
         VMSTATE_UINT8(sect, FDrive),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmstate_fdrive_media_changed,
+            .needed = &fdrive_media_changed_needed,
+        } , {
+            /* empty */
+        }
     }
 };
 
commit 33897dc7d62970acb731aab2ef2a65c225a8d64c
Author: Nick Thomas <nick at bytemark.co.uk>
Date:   Tue Feb 22 15:44:54 2011 +0000

    NBD device: Separate out parsing configuration and opening sockets.
    
    We also change the way the file parameter is parsed so IPv6 IP
    addresses can be used, e.g.: "drive=nbd:[::1]:5000"
    
    Signed-off-by: Nick Thomas <nick at bytemark.co.uk>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index c8dc763..1d6b225 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -29,96 +29,152 @@
 #include "qemu-common.h"
 #include "nbd.h"
 #include "module.h"
+#include "qemu_socket.h"
 
 #include <sys/types.h>
 #include <unistd.h>
 
 #define EN_OPTSTR ":exportname="
 
+/* #define DEBUG_NBD */
+
+#if defined(DEBUG_NBD)
+#define logout(fmt, ...) \
+                fprintf(stderr, "nbd\t%-24s" fmt, __func__, ##__VA_ARGS__)
+#else
+#define logout(fmt, ...) ((void)0)
+#endif
+
 typedef struct BDRVNBDState {
     int sock;
     off_t size;
     size_t blocksize;
+    char *export_name; /* An NBD server may export several devices */
+
+    /* If it begins with  '/', this is a UNIX domain socket. Otherwise,
+     * it's a string of the form <hostname|ip4|\[ip6\]>:port
+     */
+    char *host_spec;
 } BDRVNBDState;
 
-static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
+static int nbd_config(BDRVNBDState *s, const char *filename, int flags)
 {
-    BDRVNBDState *s = bs->opaque;
-    uint32_t nbdflags;
-
     char *file;
-    char *name;
-    const char *host;
+    char *export_name;
+    const char *host_spec;
     const char *unixpath;
-    int sock;
-    off_t size;
-    size_t blocksize;
-    int ret;
     int err = -EINVAL;
 
     file = qemu_strdup(filename);
 
-    name = strstr(file, EN_OPTSTR);
-    if (name) {
-        if (name[strlen(EN_OPTSTR)] == 0) {
+    export_name = strstr(file, EN_OPTSTR);
+    if (export_name) {
+        if (export_name[strlen(EN_OPTSTR)] == 0) {
             goto out;
         }
-        name[0] = 0;
-        name += strlen(EN_OPTSTR);
+        export_name[0] = 0; /* truncate 'file' */
+        export_name += strlen(EN_OPTSTR);
+        s->export_name = qemu_strdup(export_name);
     }
 
-    if (!strstart(file, "nbd:", &host)) {
+    /* extract the host_spec - fail if it's not nbd:... */
+    if (!strstart(file, "nbd:", &host_spec)) {
         goto out;
     }
 
-    if (strstart(host, "unix:", &unixpath)) {
-
-        if (unixpath[0] != '/') {
+    /* are we a UNIX or TCP socket? */
+    if (strstart(host_spec, "unix:", &unixpath)) {
+        if (unixpath[0] != '/') { /* We demand  an absolute path*/
             goto out;
         }
-
-        sock = unix_socket_outgoing(unixpath);
-
+        s->host_spec = qemu_strdup(unixpath);
     } else {
-        uint16_t port = NBD_DEFAULT_PORT;
-        char *p, *r;
-        char hostname[128];
+        s->host_spec = qemu_strdup(host_spec);
+    }
 
-        pstrcpy(hostname, 128, host);
+    err = 0;
 
-        p = strchr(hostname, ':');
-        if (p != NULL) {
-            *p = '\0';
-            p++;
+out:
+    qemu_free(file);
+    if (err != 0) {
+        qemu_free(s->export_name);
+        qemu_free(s->host_spec);
+    }
+    return err;
+}
 
-            port = strtol(p, &r, 0);
-            if (r == p) {
-                goto out;
-            }
-        }
+static int nbd_establish_connection(BlockDriverState *bs)
+{
+    BDRVNBDState *s = bs->opaque;
+    int sock;
+    int ret;
+    off_t size;
+    size_t blocksize;
+    uint32_t nbdflags;
 
-        sock = tcp_socket_outgoing(hostname, port);
+    if (s->host_spec[0] == '/') {
+        sock = unix_socket_outgoing(s->host_spec);
+    } else {
+        sock = tcp_socket_outgoing_spec(s->host_spec);
     }
 
+    /* Failed to establish connection */
     if (sock == -1) {
-        err = -errno;
-        goto out;
+        logout("Failed to establish connection to NBD server\n");
+        return -errno;
     }
 
-    ret = nbd_receive_negotiate(sock, name, &nbdflags, &size, &blocksize);
+    /* NBD handshake */
+    ret = nbd_receive_negotiate(sock, s->export_name, &nbdflags, &size,
+                                &blocksize);
     if (ret == -1) {
-        err = -errno;
-        goto out;
+        logout("Failed to negotiate with the NBD server\n");
+        closesocket(sock);
+        return -errno;
     }
 
+    /* Now that we're connected, set the socket to be non-blocking */
+    socket_set_nonblock(sock);
+
     s->sock = sock;
     s->size = size;
     s->blocksize = blocksize;
-    err = 0;
 
-out:
-    qemu_free(file);
-    return err;
+    logout("Established connection with NBD server\n");
+    return 0;
+}
+
+static void nbd_teardown_connection(BlockDriverState *bs)
+{
+    BDRVNBDState *s = bs->opaque;
+    struct nbd_request request;
+
+    request.type = NBD_CMD_DISC;
+    request.handle = (uint64_t)(intptr_t)bs;
+    request.from = 0;
+    request.len = 0;
+    nbd_send_request(s->sock, &request);
+
+    closesocket(s->sock);
+}
+
+static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
+{
+    BDRVNBDState *s = bs->opaque;
+    int result;
+
+    /* Pop the config into our state object. Exit if invalid. */
+    result = nbd_config(s, filename, flags);
+    if (result != 0) {
+        return result;
+    }
+
+    /* establish TCP connection, return error if it fails
+     * TODO: Configurable retry-until-timeout behaviour.
+     */
+    result = nbd_establish_connection(bs);
+
+    return result;
 }
 
 static int nbd_read(BlockDriverState *bs, int64_t sector_num,
@@ -183,16 +239,7 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num,
 
 static void nbd_close(BlockDriverState *bs)
 {
-    BDRVNBDState *s = bs->opaque;
-    struct nbd_request request;
-
-    request.type = NBD_CMD_DISC;
-    request.handle = (uint64_t)(intptr_t)bs;
-    request.from = 0;
-    request.len = 0;
-    nbd_send_request(s->sock, &request);
-
-    close(s->sock);
+    nbd_teardown_connection(bs);
 }
 
 static int64_t nbd_getlength(BlockDriverState *bs)
commit c12504ceef999c80b82c69c0154205ca23247fd5
Author: Nick Thomas <nick at bytemark.co.uk>
Date:   Tue Feb 22 15:44:53 2011 +0000

    NBD: Use qemu_socket functions to open TCP and UNIX sockets
    
    This commit has the side-effect of making the qemu-nbd binary
    capable of binding to IPv6 addresses. ("-b ::1", for instance).
    block/nbd.c fails to parse IPv6 IP addresses correctly at this
    point, but will work over IPv6 when given a hostname. It still
    works over IPv4 as before.
    
    We move the qemu-sockets object from the 'common' to the 'block'
    list in the Makefile. The common list includes the block list,
    so this is effectively a no-op for the rest of the code.
    
    We also add 32-bit 'magic' attributes to nbd_(request|reply) to
    facilitate calculating maximum request/response sizes later.
    
    Signed-off-by: Nick Thomas <nick at bytemark.co.uk>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 94587e1..44ce368 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -14,7 +14,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o
-block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o
+block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
@@ -94,7 +94,7 @@ common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
 common-obj-$(CONFIG_SD) += sd.o
 common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
 common-obj-y += bt-hci-csr.o
-common-obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
+common-obj-y += buffered_file.o migration.o migration-tcp.o
 common-obj-y += qemu-char.o savevm.o #aio.o
 common-obj-y += msmouse.o ps2.o
 common-obj-y += qdev.o qdev-properties.o
diff --git a/nbd.c b/nbd.c
index abe0ecb..0dcd86b 100644
--- a/nbd.c
+++ b/nbd.c
@@ -107,155 +107,55 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
     return offset;
 }
 
-int tcp_socket_outgoing(const char *address, uint16_t port)
+static void combine_addr(char *buf, size_t len, const char* address,
+                         uint16_t port)
 {
-    int s;
-    struct in_addr in;
-    struct sockaddr_in addr;
-
-    s = socket(PF_INET, SOCK_STREAM, 0);
-    if (s == -1) {
-        return -1;
-    }
-
-    if (inet_aton(address, &in) == 0) {
-        struct hostent *ent;
-
-        ent = gethostbyname(address);
-        if (ent == NULL) {
-            goto error;
-        }
-
-        memcpy(&in, ent->h_addr, sizeof(in));
-    }
-
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
-
-    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        goto error;
+    /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
+    if (strstr(address, ":")) {
+        snprintf(buf, len, "[%s]:%u", address, port);
+    } else {
+        snprintf(buf, len, "%s:%u", address, port);
     }
-
-    return s;
-error:
-    closesocket(s);
-    return -1;
 }
 
-int tcp_socket_incoming(const char *address, uint16_t port)
+int tcp_socket_outgoing(const char *address, uint16_t port)
 {
-    int s;
-    struct in_addr in;
-    struct sockaddr_in addr;
-    int opt;
-
-    s = socket(PF_INET, SOCK_STREAM, 0);
-    if (s == -1) {
-        return -1;
-    }
-
-    if (inet_aton(address, &in) == 0) {
-        struct hostent *ent;
-
-        ent = gethostbyname(address);
-        if (ent == NULL) {
-            goto error;
-        }
-
-        memcpy(&in, ent->h_addr, sizeof(in));
-    }
-
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
-
-    opt = 1;
-    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
-                   (const void *) &opt, sizeof(opt)) == -1) {
-        goto error;
-    }
-
-    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        goto error;
-    }
-
-    if (listen(s, 128) == -1) {
-        goto error;
-    }
-
-    return s;
-error:
-    closesocket(s);
-    return -1;
+    char address_and_port[128];
+    combine_addr(address_and_port, 128, address, port);
+    return tcp_socket_outgoing_spec(address_and_port);
 }
 
-#ifndef _WIN32
-int unix_socket_incoming(const char *path)
+int tcp_socket_outgoing_spec(const char *address_and_port)
 {
-    int s;
-    struct sockaddr_un addr;
-
-    s = socket(PF_UNIX, SOCK_STREAM, 0);
-    if (s == -1) {
-        return -1;
-    }
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
-
-    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        goto error;
-    }
-
-    if (listen(s, 128) == -1) {
-        goto error;
-    }
-
-    return s;
-error:
-    closesocket(s);
-    return -1;
+    return inet_connect(address_and_port, SOCK_STREAM);
 }
 
-int unix_socket_outgoing(const char *path)
+int tcp_socket_incoming(const char *address, uint16_t port)
 {
-    int s;
-    struct sockaddr_un addr;
-
-    s = socket(PF_UNIX, SOCK_STREAM, 0);
-    if (s == -1) {
-        return -1;
-    }
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
-
-    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        goto error;
-    }
+    char address_and_port[128];
+    combine_addr(address_and_port, 128, address, port);
+    return tcp_socket_incoming_spec(address_and_port);
+}
 
-    return s;
-error:
-    closesocket(s);
-    return -1;
+int tcp_socket_incoming_spec(const char *address_and_port)
+{
+    char *ostr  = NULL;
+    int olen = 0;
+    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
 }
-#else
+
 int unix_socket_incoming(const char *path)
 {
-    errno = ENOTSUP;
-    return -1;
+    char *ostr = NULL;
+    int olen = 0;
+
+    return unix_listen(path, ostr, olen);
 }
 
 int unix_socket_outgoing(const char *path)
 {
-    errno = ENOTSUP;
-    return -1;
+    return unix_connect(path);
 }
-#endif
-
 
 /* Basic flow
 
diff --git a/nbd.h b/nbd.h
index fc3a594..b38d0d0 100644
--- a/nbd.h
+++ b/nbd.h
@@ -22,19 +22,22 @@
 #include <sys/types.h>
 
 #include <qemu-common.h>
+
 #include "block_int.h"
 
 struct nbd_request {
+    uint32_t magic;
     uint32_t type;
     uint64_t handle;
     uint64_t from;
     uint32_t len;
-};
+} __attribute__ ((__packed__));
 
 struct nbd_reply {
+    uint32_t magic;
     uint32_t error;
     uint64_t handle;
-};
+} __attribute__ ((__packed__));
 
 enum {
     NBD_CMD_READ = 0,
@@ -47,6 +50,8 @@ enum {
 size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
 int tcp_socket_outgoing(const char *address, uint16_t port);
 int tcp_socket_incoming(const char *address, uint16_t port);
+int tcp_socket_outgoing_spec(const char *address_and_port);
+int tcp_socket_incoming_spec(const char *address_and_port);
 int unix_socket_outgoing(const char *path);
 int unix_socket_incoming(const char *path);
 
commit b82eac92ac69a22243d341dde0213b7d15d7ba24
Author: Nick Thomas <nick at bytemark.co.uk>
Date:   Tue Feb 22 15:44:52 2011 +0000

    Set errno=ENOTSUP for attempts to use UNIX sockets on Windows platforms
    
    Signed-off-by: Nick Thomas <nick at bytemark.co.uk>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-sockets.c b/qemu-sockets.c
index c526324..eda1850 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -627,24 +627,28 @@ int unix_connect(const char *path)
 int unix_listen_opts(QemuOpts *opts)
 {
     fprintf(stderr, "unix sockets are not available on windows\n");
+    errno = ENOTSUP;
     return -1;
 }
 
 int unix_connect_opts(QemuOpts *opts)
 {
     fprintf(stderr, "unix sockets are not available on windows\n");
+    errno = ENOTSUP;
     return -1;
 }
 
 int unix_listen(const char *path, char *ostr, int olen)
 {
     fprintf(stderr, "unix sockets are not available on windows\n");
+    errno = ENOTSUP;
     return -1;
 }
 
 int unix_connect(const char *path)
 {
     fprintf(stderr, "unix sockets are not available on windows\n");
+    errno = ENOTSUP;
     return -1;
 }
 
commit b2e3d87f043d02f2fba03c8463c9ad3d0478c869
Author: Nick Thomas <nick at bytemark.co.uk>
Date:   Tue Feb 22 15:44:51 2011 +0000

    NBD library: whitespace changes
    
    Signed-off-by: Nick Thomas <nick at bytemark.co.uk>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/nbd.c b/nbd.c
index d8ebc42..abe0ecb 100644
--- a/nbd.c
+++ b/nbd.c
@@ -49,7 +49,7 @@
 
 /* This is all part of the "official" NBD API */
 
-#define NBD_REPLY_SIZE		(4 + 4 + 8)
+#define NBD_REPLY_SIZE          (4 + 4 + 8)
 #define NBD_REQUEST_MAGIC       0x25609513
 #define NBD_REPLY_MAGIC         0x67446698
 
@@ -59,11 +59,11 @@
 #define NBD_DO_IT               _IO(0xab, 3)
 #define NBD_CLEAR_SOCK          _IO(0xab, 4)
 #define NBD_CLEAR_QUE           _IO(0xab, 5)
-#define NBD_PRINT_DEBUG	        _IO(0xab, 6)
-#define NBD_SET_SIZE_BLOCKS	_IO(0xab, 7)
+#define NBD_PRINT_DEBUG         _IO(0xab, 6)
+#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
 #define NBD_DISCONNECT          _IO(0xab, 8)
 
-#define NBD_OPT_EXPORT_NAME	(1 << 0)
+#define NBD_OPT_EXPORT_NAME     (1 << 0)
 
 /* That's all folks */
 
@@ -273,241 +273,241 @@ int unix_socket_outgoing(const char *path)
 
 int nbd_negotiate(int csock, off_t size)
 {
-	char buf[8 + 8 + 8 + 128];
-
-	/* Negotiate
-	   [ 0 ..   7]   passwd   ("NBDMAGIC")
-	   [ 8 ..  15]   magic    (0x00420281861253)
-	   [16 ..  23]   size
-	   [24 .. 151]   reserved (0)
-	 */
-
-	TRACE("Beginning negotiation.");
-	memcpy(buf, "NBDMAGIC", 8);
-	cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
-	cpu_to_be64w((uint64_t*)(buf + 16), size);
-	memset(buf + 24, 0, 128);
-
-	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
-		LOG("write failed");
-		errno = EINVAL;
-		return -1;
-	}
-
-	TRACE("Negotation succeeded.");
-
-	return 0;
+    char buf[8 + 8 + 8 + 128];
+
+    /* Negotiate
+        [ 0 ..   7]   passwd   ("NBDMAGIC")
+        [ 8 ..  15]   magic    (0x00420281861253)
+        [16 ..  23]   size
+        [24 .. 151]   reserved (0)
+     */
+
+    TRACE("Beginning negotiation.");
+    memcpy(buf, "NBDMAGIC", 8);
+    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
+    cpu_to_be64w((uint64_t*)(buf + 16), size);
+    memset(buf + 24, 0, 128);
+
+    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
+        LOG("write failed");
+        errno = EINVAL;
+        return -1;
+    }
+
+    TRACE("Negotation succeeded.");
+
+    return 0;
 }
 
 int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
                           off_t *size, size_t *blocksize)
 {
-	char buf[256];
-	uint64_t magic, s;
-	uint16_t tmp;
-
-	TRACE("Receiving negotation.");
-
-	if (read_sync(csock, buf, 8) != 8) {
-		LOG("read failed");
-		errno = EINVAL;
-		return -1;
-	}
-
-	buf[8] = '\0';
-	if (strlen(buf) == 0) {
-		LOG("server connection closed");
-		errno = EINVAL;
-		return -1;
-	}
-
-	TRACE("Magic is %c%c%c%c%c%c%c%c",
-	      qemu_isprint(buf[0]) ? buf[0] : '.',
-	      qemu_isprint(buf[1]) ? buf[1] : '.',
-	      qemu_isprint(buf[2]) ? buf[2] : '.',
-	      qemu_isprint(buf[3]) ? buf[3] : '.',
-	      qemu_isprint(buf[4]) ? buf[4] : '.',
-	      qemu_isprint(buf[5]) ? buf[5] : '.',
-	      qemu_isprint(buf[6]) ? buf[6] : '.',
-	      qemu_isprint(buf[7]) ? buf[7] : '.');
-
-	if (memcmp(buf, "NBDMAGIC", 8) != 0) {
-		LOG("Invalid magic received");
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
-		LOG("read failed");
-		errno = EINVAL;
-		return -1;
-	}
-	magic = be64_to_cpu(magic);
-	TRACE("Magic is 0x%" PRIx64, magic);
-
-	if (name) {
-		uint32_t reserved = 0;
-		uint32_t opt;
-		uint32_t namesize;
-
-		TRACE("Checking magic (opts_magic)");
-		if (magic != 0x49484156454F5054LL) {
-			LOG("Bad magic received");
-			errno = EINVAL;
-			return -1;
-		}
-		if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-			LOG("flags read failed");
-			errno = EINVAL;
-			return -1;
-		}
-		*flags = be16_to_cpu(tmp) << 16;
-		/* reserved for future use */
-		if (write_sync(csock, &reserved, sizeof(reserved)) !=
-		    sizeof(reserved)) {
-			LOG("write failed (reserved)");
-			errno = EINVAL;
-			return -1;
-		}
-		/* write the export name */
-		magic = cpu_to_be64(magic);
-		if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
-			LOG("write failed (magic)");
-			errno = EINVAL;
-			return -1;
-		}
-		opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
-		if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
-			LOG("write failed (opt)");
-			errno = EINVAL;
-			return -1;
-		}
-		namesize = cpu_to_be32(strlen(name));
-		if (write_sync(csock, &namesize, sizeof(namesize)) !=
-		    sizeof(namesize)) {
-			LOG("write failed (namesize)");
-			errno = EINVAL;
-			return -1;
-		}
-		if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
-			LOG("write failed (name)");
-			errno = EINVAL;
-			return -1;
-		}
-	} else {
-		TRACE("Checking magic (cli_magic)");
-
-		if (magic != 0x00420281861253LL) {
-			LOG("Bad magic received");
-			errno = EINVAL;
-			return -1;
-		}
-	}
-
-	if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
-		LOG("read failed");
-		errno = EINVAL;
-		return -1;
-	}
-	*size = be64_to_cpu(s);
-	*blocksize = 1024;
-	TRACE("Size is %" PRIu64, *size);
-
-	if (!name) {
-		if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
-			LOG("read failed (flags)");
-			errno = EINVAL;
-			return -1;
-		}
-		*flags = be32_to_cpup(flags);
-	} else {
-		if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-			LOG("read failed (tmp)");
-			errno = EINVAL;
-			return -1;
-		}
-		*flags |= be32_to_cpu(tmp);
-	}
-	if (read_sync(csock, &buf, 124) != 124) {
-		LOG("read failed (buf)");
-		errno = EINVAL;
-		return -1;
-	}
+    char buf[256];
+    uint64_t magic, s;
+    uint16_t tmp;
+
+    TRACE("Receiving negotation.");
+
+    if (read_sync(csock, buf, 8) != 8) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+
+    buf[8] = '\0';
+    if (strlen(buf) == 0) {
+        LOG("server connection closed");
+        errno = EINVAL;
+        return -1;
+    }
+
+    TRACE("Magic is %c%c%c%c%c%c%c%c",
+          qemu_isprint(buf[0]) ? buf[0] : '.',
+          qemu_isprint(buf[1]) ? buf[1] : '.',
+          qemu_isprint(buf[2]) ? buf[2] : '.',
+          qemu_isprint(buf[3]) ? buf[3] : '.',
+          qemu_isprint(buf[4]) ? buf[4] : '.',
+          qemu_isprint(buf[5]) ? buf[5] : '.',
+          qemu_isprint(buf[6]) ? buf[6] : '.',
+          qemu_isprint(buf[7]) ? buf[7] : '.');
+
+    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
+        LOG("Invalid magic received");
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    magic = be64_to_cpu(magic);
+    TRACE("Magic is 0x%" PRIx64, magic);
+
+    if (name) {
+        uint32_t reserved = 0;
+        uint32_t opt;
+        uint32_t namesize;
+
+        TRACE("Checking magic (opts_magic)");
+        if (magic != 0x49484156454F5054LL) {
+            LOG("Bad magic received");
+            errno = EINVAL;
+            return -1;
+        }
+        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+            LOG("flags read failed");
+            errno = EINVAL;
+            return -1;
+        }
+        *flags = be16_to_cpu(tmp) << 16;
+        /* reserved for future use */
+        if (write_sync(csock, &reserved, sizeof(reserved)) !=
+            sizeof(reserved)) {
+            LOG("write failed (reserved)");
+            errno = EINVAL;
+            return -1;
+        }
+        /* write the export name */
+        magic = cpu_to_be64(magic);
+        if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
+            LOG("write failed (magic)");
+            errno = EINVAL;
+            return -1;
+        }
+        opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
+        if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
+            LOG("write failed (opt)");
+            errno = EINVAL;
+            return -1;
+        }
+        namesize = cpu_to_be32(strlen(name));
+        if (write_sync(csock, &namesize, sizeof(namesize)) !=
+            sizeof(namesize)) {
+            LOG("write failed (namesize)");
+            errno = EINVAL;
+            return -1;
+        }
+        if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
+            LOG("write failed (name)");
+            errno = EINVAL;
+            return -1;
+        }
+    } else {
+        TRACE("Checking magic (cli_magic)");
+
+        if (magic != 0x00420281861253LL) {
+            LOG("Bad magic received");
+            errno = EINVAL;
+            return -1;
+        }
+    }
+
+    if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+    *size = be64_to_cpu(s);
+    *blocksize = 1024;
+    TRACE("Size is %" PRIu64, *size);
+
+    if (!name) {
+        if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
+            LOG("read failed (flags)");
+            errno = EINVAL;
+            return -1;
+        }
+        *flags = be32_to_cpup(flags);
+    } else {
+        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+            LOG("read failed (tmp)");
+            errno = EINVAL;
+            return -1;
+        }
+        *flags |= be32_to_cpu(tmp);
+    }
+    if (read_sync(csock, &buf, 124) != 124) {
+        LOG("read failed (buf)");
+        errno = EINVAL;
+        return -1;
+    }
         return 0;
 }
 
 #ifndef _WIN32
 int nbd_init(int fd, int csock, off_t size, size_t blocksize)
 {
-	TRACE("Setting block size to %lu", (unsigned long)blocksize);
+    TRACE("Setting block size to %lu", (unsigned long)blocksize);
 
-	if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
-		int serrno = errno;
-		LOG("Failed setting NBD block size");
-		errno = serrno;
-		return -1;
-	}
+    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
+        int serrno = errno;
+        LOG("Failed setting NBD block size");
+        errno = serrno;
+        return -1;
+    }
 
         TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
 
-	if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
-		int serrno = errno;
-		LOG("Failed setting size (in blocks)");
-		errno = serrno;
-		return -1;
-	}
+    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
+        int serrno = errno;
+        LOG("Failed setting size (in blocks)");
+        errno = serrno;
+        return -1;
+    }
 
-	TRACE("Clearing NBD socket");
+    TRACE("Clearing NBD socket");
 
-	if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
-		int serrno = errno;
-		LOG("Failed clearing NBD socket");
-		errno = serrno;
-		return -1;
-	}
+    if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
+        int serrno = errno;
+        LOG("Failed clearing NBD socket");
+        errno = serrno;
+        return -1;
+    }
 
-	TRACE("Setting NBD socket");
+    TRACE("Setting NBD socket");
 
-	if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
-		int serrno = errno;
-		LOG("Failed to set NBD socket");
-		errno = serrno;
-		return -1;
-	}
+    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
+        int serrno = errno;
+        LOG("Failed to set NBD socket");
+        errno = serrno;
+        return -1;
+    }
 
-	TRACE("Negotiation ended");
+    TRACE("Negotiation ended");
 
-	return 0;
+    return 0;
 }
 
 int nbd_disconnect(int fd)
 {
-	ioctl(fd, NBD_CLEAR_QUE);
-	ioctl(fd, NBD_DISCONNECT);
-	ioctl(fd, NBD_CLEAR_SOCK);
-	return 0;
+    ioctl(fd, NBD_CLEAR_QUE);
+    ioctl(fd, NBD_DISCONNECT);
+    ioctl(fd, NBD_CLEAR_SOCK);
+    return 0;
 }
 
 int nbd_client(int fd)
 {
-	int ret;
-	int serrno;
+    int ret;
+    int serrno;
 
-	TRACE("Doing NBD loop");
+    TRACE("Doing NBD loop");
 
-	ret = ioctl(fd, NBD_DO_IT);
-	serrno = errno;
+    ret = ioctl(fd, NBD_DO_IT);
+    serrno = errno;
 
-	TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
+    TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
 
-	TRACE("Clearing NBD queue");
-	ioctl(fd, NBD_CLEAR_QUE);
+    TRACE("Clearing NBD queue");
+    ioctl(fd, NBD_CLEAR_QUE);
 
-	TRACE("Clearing NBD socket");
-	ioctl(fd, NBD_CLEAR_SOCK);
+    TRACE("Clearing NBD socket");
+    ioctl(fd, NBD_CLEAR_SOCK);
 
-	errno = serrno;
-	return ret;
+    errno = serrno;
+    return ret;
 }
 #else
 int nbd_init(int fd, int csock, off_t size, size_t blocksize)
@@ -531,235 +531,236 @@ int nbd_client(int fd)
 
 int nbd_send_request(int csock, struct nbd_request *request)
 {
-	uint8_t buf[4 + 4 + 8 + 8 + 4];
-
-	cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
-	cpu_to_be32w((uint32_t*)(buf + 4), request->type);
-	cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
-	cpu_to_be64w((uint64_t*)(buf + 16), request->from);
-	cpu_to_be32w((uint32_t*)(buf + 24), request->len);
-
-	TRACE("Sending request to client");
-
-	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
-		LOG("writing to socket failed");
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
-}
+    uint8_t buf[4 + 4 + 8 + 8 + 4];
+
+    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
+    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
+    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
+    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
+    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
 
+    TRACE("Sending request to client: "
+          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
+          request->from, request->len, request->handle, request->type);
+
+    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
+        LOG("writing to socket failed");
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
 
 static int nbd_receive_request(int csock, struct nbd_request *request)
 {
-	uint8_t buf[4 + 4 + 8 + 8 + 4];
-	uint32_t magic;
-
-	if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
-		LOG("read failed");
-		errno = EINVAL;
-		return -1;
-	}
-
-	/* Request
-	   [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
-	   [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
-	   [ 8 .. 15]   handle
-	   [16 .. 23]   from
-	   [24 .. 27]   len
-	 */
-
-	magic = be32_to_cpup((uint32_t*)buf);
-	request->type  = be32_to_cpup((uint32_t*)(buf + 4));
-	request->handle = be64_to_cpup((uint64_t*)(buf + 8));
-	request->from  = be64_to_cpup((uint64_t*)(buf + 16));
-	request->len   = be32_to_cpup((uint32_t*)(buf + 24));
-
-	TRACE("Got request: "
-	      "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
-	      magic, request->type, request->from, request->len);
-
-	if (magic != NBD_REQUEST_MAGIC) {
-		LOG("invalid magic (got 0x%x)", magic);
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
+    uint8_t buf[4 + 4 + 8 + 8 + 4];
+    uint32_t magic;
+
+    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* Request
+       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
+       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
+       [ 8 .. 15]   handle
+       [16 .. 23]   from
+       [24 .. 27]   len
+     */
+
+    magic = be32_to_cpup((uint32_t*)buf);
+    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
+    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
+    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
+    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
+
+    TRACE("Got request: "
+          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
+          magic, request->type, request->from, request->len);
+
+    if (magic != NBD_REQUEST_MAGIC) {
+        LOG("invalid magic (got 0x%x)", magic);
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
 }
 
 int nbd_receive_reply(int csock, struct nbd_reply *reply)
 {
-	uint8_t buf[NBD_REPLY_SIZE];
-	uint32_t magic;
-
-	memset(buf, 0xAA, sizeof(buf));
-
-	if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
-		LOG("read failed");
-		errno = EINVAL;
-		return -1;
-	}
-
-	/* Reply
-	   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
-	   [ 4 ..  7]    error   (0 == no error)
-	   [ 7 .. 15]    handle
-	 */
-
-	magic = be32_to_cpup((uint32_t*)buf);
-	reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
-	reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
-
-	TRACE("Got reply: "
-	      "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
-	      magic, reply->error, reply->handle);
-
-	if (magic != NBD_REPLY_MAGIC) {
-		LOG("invalid magic (got 0x%x)", magic);
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
+    uint8_t buf[NBD_REPLY_SIZE];
+    uint32_t magic;
+
+    memset(buf, 0xAA, sizeof(buf));
+
+    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
+        LOG("read failed");
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* Reply
+       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
+       [ 4 ..  7]    error   (0 == no error)
+       [ 7 .. 15]    handle
+     */
+
+    magic = be32_to_cpup((uint32_t*)buf);
+    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
+    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
+
+    TRACE("Got reply: "
+          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
+          magic, reply->error, reply->handle);
+
+    if (magic != NBD_REPLY_MAGIC) {
+        LOG("invalid magic (got 0x%x)", magic);
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
 }
 
 static int nbd_send_reply(int csock, struct nbd_reply *reply)
 {
-	uint8_t buf[4 + 4 + 8];
-
-	/* Reply
-	   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
-	   [ 4 ..  7]    error   (0 == no error)
-	   [ 7 .. 15]    handle
-	 */
-	cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
-	cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
-	cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
-
-	TRACE("Sending response to client");
-
-	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
-		LOG("writing to socket failed");
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
+    uint8_t buf[4 + 4 + 8];
+
+    /* Reply
+       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
+       [ 4 ..  7]    error   (0 == no error)
+       [ 7 .. 15]    handle
+     */
+    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
+    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
+    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
+
+    TRACE("Sending response to client");
+
+    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
+        LOG("writing to socket failed");
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
 }
 
 int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
              off_t *offset, bool readonly, uint8_t *data, int data_size)
 {
-	struct nbd_request request;
-	struct nbd_reply reply;
-
-	TRACE("Reading request.");
-
-	if (nbd_receive_request(csock, &request) == -1)
-		return -1;
-
-	if (request.len + NBD_REPLY_SIZE > data_size) {
-		LOG("len (%u) is larger than max len (%u)",
-		    request.len + NBD_REPLY_SIZE, data_size);
-		errno = EINVAL;
-		return -1;
-	}
-
-	if ((request.from + request.len) < request.from) {
-		LOG("integer overflow detected! "
-		    "you're probably being attacked");
-		errno = EINVAL;
-		return -1;
-	}
-
-	if ((request.from + request.len) > size) {
-	        LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
-		    ", Offset: %" PRIu64 "\n",
+    struct nbd_request request;
+    struct nbd_reply reply;
+
+    TRACE("Reading request.");
+
+    if (nbd_receive_request(csock, &request) == -1)
+        return -1;
+
+    if (request.len + NBD_REPLY_SIZE > data_size) {
+        LOG("len (%u) is larger than max len (%u)",
+            request.len + NBD_REPLY_SIZE, data_size);
+        errno = EINVAL;
+        return -1;
+    }
+
+    if ((request.from + request.len) < request.from) {
+        LOG("integer overflow detected! "
+            "you're probably being attacked");
+        errno = EINVAL;
+        return -1;
+    }
+
+    if ((request.from + request.len) > size) {
+            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
+            ", Offset: %" PRIu64 "\n",
                     request.from, request.len, (uint64_t)size, dev_offset);
-		LOG("requested operation past EOF--bad client?");
-		errno = EINVAL;
-		return -1;
-	}
-
-	TRACE("Decoding type");
-
-	reply.handle = request.handle;
-	reply.error = 0;
-
-	switch (request.type) {
-	case NBD_CMD_READ:
-		TRACE("Request type is READ");
-
-		if (bdrv_read(bs, (request.from + dev_offset) / 512,
-			      data + NBD_REPLY_SIZE,
-			      request.len / 512) == -1) {
-			LOG("reading from file failed");
-			errno = EINVAL;
-			return -1;
-		}
-		*offset += request.len;
-
-		TRACE("Read %u byte(s)", request.len);
-
-		/* Reply
-		   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
-		   [ 4 ..  7]    error   (0 == no error)
-		   [ 7 .. 15]    handle
-		 */
-
-		cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
-		cpu_to_be32w((uint32_t*)(data + 4), reply.error);
-		cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
-
-		TRACE("Sending data to client");
-
-		if (write_sync(csock, data,
-			       request.len + NBD_REPLY_SIZE) !=
-			       request.len + NBD_REPLY_SIZE) {
-			LOG("writing to socket failed");
-			errno = EINVAL;
-			return -1;
-		}
-		break;
-	case NBD_CMD_WRITE:
-		TRACE("Request type is WRITE");
-
-		TRACE("Reading %u byte(s)", request.len);
-
-		if (read_sync(csock, data, request.len) != request.len) {
-			LOG("reading from socket failed");
-			errno = EINVAL;
-			return -1;
-		}
-
-		if (readonly) {
-			TRACE("Server is read-only, return error");
-			reply.error = 1;
-		} else {
-			TRACE("Writing to device");
-
-			if (bdrv_write(bs, (request.from + dev_offset) / 512,
-				       data, request.len / 512) == -1) {
-				LOG("writing to file failed");
-				errno = EINVAL;
-				return -1;
-			}
-
-			*offset += request.len;
-		}
-
-		if (nbd_send_reply(csock, &reply) == -1)
-			return -1;
-		break;
-	case NBD_CMD_DISC:
-		TRACE("Request type is DISCONNECT");
-		errno = 0;
-		return 1;
-	default:
-		LOG("invalid request type (%u) received", request.type);
-		errno = EINVAL;
-		return -1;
-	}
-
-	TRACE("Request/Reply complete");
-
-	return 0;
+        LOG("requested operation past EOF--bad client?");
+        errno = EINVAL;
+        return -1;
+    }
+
+    TRACE("Decoding type");
+
+    reply.handle = request.handle;
+    reply.error = 0;
+
+    switch (request.type) {
+    case NBD_CMD_READ:
+        TRACE("Request type is READ");
+
+        if (bdrv_read(bs, (request.from + dev_offset) / 512,
+                  data + NBD_REPLY_SIZE,
+                  request.len / 512) == -1) {
+            LOG("reading from file failed");
+            errno = EINVAL;
+            return -1;
+        }
+        *offset += request.len;
+
+        TRACE("Read %u byte(s)", request.len);
+
+        /* Reply
+           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
+           [ 4 ..  7]    error   (0 == no error)
+           [ 7 .. 15]    handle
+         */
+
+        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
+        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
+        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
+
+        TRACE("Sending data to client");
+
+        if (write_sync(csock, data,
+                   request.len + NBD_REPLY_SIZE) !=
+                   request.len + NBD_REPLY_SIZE) {
+            LOG("writing to socket failed");
+            errno = EINVAL;
+            return -1;
+        }
+        break;
+    case NBD_CMD_WRITE:
+        TRACE("Request type is WRITE");
+
+        TRACE("Reading %u byte(s)", request.len);
+
+        if (read_sync(csock, data, request.len) != request.len) {
+            LOG("reading from socket failed");
+            errno = EINVAL;
+            return -1;
+        }
+
+        if (readonly) {
+            TRACE("Server is read-only, return error");
+            reply.error = 1;
+        } else {
+            TRACE("Writing to device");
+
+            if (bdrv_write(bs, (request.from + dev_offset) / 512,
+                       data, request.len / 512) == -1) {
+                LOG("writing to file failed");
+                errno = EINVAL;
+                return -1;
+            }
+
+            *offset += request.len;
+        }
+
+        if (nbd_send_reply(csock, &reply) == -1)
+            return -1;
+        break;
+    case NBD_CMD_DISC:
+        TRACE("Request type is DISCONNECT");
+        errno = 0;
+        return 1;
+    default:
+        LOG("invalid request type (%u) received", request.type);
+        errno = EINVAL;
+        return -1;
+    }
+
+    TRACE("Request/Reply complete");
+
+    return 0;
 }
commit 757179038c4884dc43c2ecd0f4da3facb24f262c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Sun Apr 3 20:32:46 2011 +0900

    ide: consolidate drive_get(IF_IDE)
    
    factor out ide initialization to call drive_get(IF_IDE)
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide.h b/hw/ide.h
index 73fb550..34d9394 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -28,4 +28,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
 
 void ide_get_bs(BlockDriverState *bs[], BusState *qbus);
 
+/* ide/core.c */
+void ide_drive_get(DriveInfo **hd, int max_bus);
+
 #endif /* HW_IDE_H */
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 007a4ee..c11d457 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2826,3 +2826,17 @@ const VMStateDescription vmstate_ide_bus = {
         VMSTATE_END_OF_LIST()
     }
 };
+
+void ide_drive_get(DriveInfo **hd, int max_bus)
+{
+    int i;
+
+    if (drive_get_max_bus(IF_IDE) >= max_bus) {
+        fprintf(stderr, "qemu: too many IDE bus: %d\n", max_bus);
+        exit(1);
+    }
+
+    for(i = 0; i < max_bus * MAX_IDE_DEVS; i++) {
+        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+    }
+}
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index f5ae639..0e90d68 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -338,14 +338,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
 
     /* South bridge */
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
 
     via_devfn = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
     if (via_devfn < 0) {
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d8baa6d..bf0d76d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -905,15 +905,7 @@ void mips_malta_init (ram_addr_t ram_size,
     pci_bus = gt64120_register(i8259);
 
     /* Southbridge */
-
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
 
     piix4_devfn = piix4_init(pci_bus, 80);
     isa_bus_irqs(i8259);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 8feb461..2834a46 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -287,15 +287,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     if (nd_table[0].vlan)
         isa_ne2000_init(0x300, 9, &nd_table[0]);
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
-
+    ide_drive_get(hd, MAX_IDE_BUS);
     for(i = 0; i < MAX_IDE_BUS; i++)
         isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[MAX_IDE_DEVS * i],
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b3ede89..4d54ca1 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -129,15 +129,7 @@ static void pc_init1(ram_addr_t ram_size,
             pci_nic_init_nofail(nd, "e1000", NULL);
     }
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
-
+    ide_drive_get(hd, MAX_IDE_BUS);
     if (pci_enabled) {
         PCIDevice *dev;
         dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index b9245f0..86f1cfb 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -325,20 +325,13 @@ static void ppc_core99_init (ram_addr_t ram_size,
     for(i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
     dbdma = DBDMA_init(&dbdma_mem_index);
 
     /* We only emulate 2 out of 3 IDE controllers for now */
     ide_mem_index[0] = -1;
-    hd[0] = drive_get(IF_IDE, 0, 0);
-    hd[1] = drive_get(IF_IDE, 0, 1);
     ide_mem_index[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);
-    hd[0] = drive_get(IF_IDE, 1, 0);
-    hd[1] = drive_get(IF_IDE, 1, 1);
-    ide_mem_index[2] = pmac_ide_init(hd, pic[0x0e], dbdma, 0x1a, pic[0x02]);
+    ide_mem_index[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]);
 
     /* cuda also initialize ADB */
     if (machine_arch == ARCH_MAC99_U3) {
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 8a4e088..75a3127 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -236,21 +236,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
 
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
 
     /* First IDE channel is a MAC IDE on the MacIO bus */
-    hd[0] = drive_get(IF_IDE, 0, 0);
-    hd[1] = drive_get(IF_IDE, 0, 1);
     dbdma = DBDMA_init(&dbdma_mem_index);
     ide_mem_index[0] = -1;
     ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
 
     /* Second IDE channel is a CMD646 on the PCI bus */
-    hd[0] = drive_get(IF_IDE, 1, 0);
-    hd[1] = drive_get(IF_IDE, 1, 1);
+    hd[0] = hd[MAX_IDE_DEVS];
+    hd[1] = hd[MAX_IDE_DEVS + 1];
     hd[3] = hd[2] = NULL;
     pci_cmd646_ide_init(pci_bus, hd, 0);
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 5615ef9..0e9cfc2 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -681,15 +681,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         }
     }
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
-
+    ide_drive_get(hd, MAX_IDE_BUS);
     for(i = 0; i < MAX_IDE_BUS; i++) {
         isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[2 * i],
diff --git a/hw/sun4u.c b/hw/sun4u.c
index dbb5a15..5eb38cf 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -793,14 +793,7 @@ static void sun4uv_init(ram_addr_t RAM_size,
     for(i = 0; i < nb_nics; i++)
         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
 
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS,
-                          i % MAX_IDE_DEVS);
-    }
+    ide_drive_get(hd, MAX_IDE_BUS);
 
     pci_cmd646_ide_init(pci_bus, hd, 1);
 
commit e2982c3a27ab4c0879e61de3c9c57b838f7d0966
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Wed Mar 30 16:31:05 2011 +0400

    exit if -drive specified is invalid instead of ignoring the "wrong" -drive
    
    This fixes the problem when qemu continues even if -drive specification
    is somehow invalid, resulting in a mess.  Applicable for both current
    master and for stable-0.14 (and the same issue exist 0.13 and 0.12 too).
    
    The prob can actually be seriuos: when you start guest with two drives
    and make an error in the specification of one of them, and the guest
    has something like a raid array on the two drives, guest may start failing
    that array or kick "missing" drives which may result in a mess - this is
    what actually happened to me, I did't want a resync at all, and a resync
    resulted in re-writing (and allocating) a 4TB virtual drive I used for
    testing, which in turn resulted in my filesystem filling up and whole
    thing failing badly.  Yes it was just testing VM, I experimented with
    larger raid arrays, but the end result was quite, well, unexpected.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/vl.c b/vl.c
index de232b7..68c3b53 100644
--- a/vl.c
+++ b/vl.c
@@ -2102,7 +2102,9 @@ int main(int argc, char **argv, char **envp)
                           HD_OPTS);
                 break;
             case QEMU_OPTION_drive:
-                drive_def(optarg);
+                if (drive_def(optarg) == NULL) {
+                    exit(1);
+                }
 	        break;
             case QEMU_OPTION_set:
                 if (qemu_set_option(optarg) != 0)
commit eb863add0204210480d018a3298ca22e4eadf3ce
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Mar 31 12:39:51 2011 +0200

    qemu-img rebase: Fix segfault if backing file can't be opened
    
    bdrv_delete must not be called for a NULL BlockDriverState.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-img.c b/qemu-img.c
index 074388c..d9c2c12 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1411,8 +1411,12 @@ out:
     qemu_progress_end();
     /* Cleanup */
     if (!unsafe) {
-        bdrv_delete(bs_old_backing);
-        bdrv_delete(bs_new_backing);
+        if (bs_old_backing != NULL) {
+            bdrv_delete(bs_old_backing);
+        }
+        if (bs_new_backing != NULL) {
+            bdrv_delete(bs_new_backing);
+        }
     }
 
     bdrv_delete(bs);
commit 6b837bc4a4d81861027c74f882d8c1d43f4ec30c
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 30 14:16:25 2011 +0200

    qemu-img: Initial progress printing support
    
    This adds the basic infrastructure for supporting progress output
    on the command line, as well as progress support for qemu-img commands
    'rebase' and 'convert'.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index c05f5e5..94587e1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -14,7 +14,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o
-block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o
+block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
diff --git a/qemu-common.h b/qemu-common.h
index 8ecb488..82e27c1 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -334,6 +334,10 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
 void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
                             size_t skip);
 
+void qemu_progress_init(int enabled, float min_skip);
+void qemu_progress_end(void);
+void qemu_progress_print(float percent, int max);
+
 /* Convert a byte between binary and BCD.  */
 static inline uint8_t to_bcd(uint8_t val)
 {
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 6c7176f..3072d38 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -28,7 +28,7 @@ STEXI
 ETEXI
 
 DEF("convert", img_convert,
-    "convert [-c] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
+    "convert [-c] [-p] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
 STEXI
 @item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 ETEXI
@@ -46,7 +46,7 @@ STEXI
 ETEXI
 
 DEF("rebase", img_rebase,
-    "rebase [-f fmt] [-u] -b backing_file [-F backing_fmt] filename")
+    "rebase [-f fmt] [-p] [-u] -b backing_file [-F backing_fmt] filename")
 STEXI
 @item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
 ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index 7e3cc4c..074388c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -77,6 +77,7 @@ static void help(void)
            "       match exactly. The image doesn't need a working backing file before\n"
            "       rebasing in this case (useful for renaming the backing file)\n"
            "  '-h' with or without a command shows this help and lists the supported formats\n"
+           "  '-p' show progress of command (only certain commands)\n"
            "\n"
            "Parameters to snapshot subcommand:\n"
            "  'snapshot' is the name of the snapshot to create, apply or delete\n"
@@ -567,6 +568,7 @@ static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
 static int img_convert(int argc, char **argv)
 {
     int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
+    int progress = 0;
     const char *fmt, *out_fmt, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
     BlockDriverState **bs = NULL, *out_bs = NULL;
@@ -579,13 +581,14 @@ static int img_convert(int argc, char **argv)
     QEMUOptionParameter *out_baseimg_param;
     char *options = NULL;
     const char *snapshot_name = NULL;
+    float local_progress;
 
     fmt = NULL;
     out_fmt = "raw";
     out_baseimg = NULL;
     compress = 0;
     for(;;) {
-        c = getopt(argc, argv, "f:O:B:s:hce6o:");
+        c = getopt(argc, argv, "f:O:B:s:hce6o:p");
         if (c == -1) {
             break;
         }
@@ -620,6 +623,9 @@ static int img_convert(int argc, char **argv)
         case 's':
             snapshot_name = optarg;
             break;
+        case 'p':
+            progress = 1;
+            break;
         }
     }
 
@@ -642,6 +648,9 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
         
+    qemu_progress_init(progress, 2.0);
+    qemu_progress_print(0, 100);
+
     bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
 
     total_sectors = 0;
@@ -773,6 +782,11 @@ static int img_convert(int argc, char **argv)
         }
         cluster_sectors = cluster_size >> 9;
         sector_num = 0;
+
+        nb_sectors = total_sectors;
+        local_progress = (float)100 /
+            (nb_sectors / MIN(nb_sectors, (cluster_sectors)));
+
         for(;;) {
             int64_t bs_num;
             int remainder;
@@ -832,6 +846,7 @@ static int img_convert(int argc, char **argv)
                 }
             }
             sector_num += n;
+            qemu_progress_print(local_progress, 100);
         }
         /* signal EOF to align */
         bdrv_write_compressed(out_bs, 0, NULL, 0);
@@ -839,6 +854,10 @@ static int img_convert(int argc, char **argv)
         int has_zero_init = bdrv_has_zero_init(out_bs);
 
         sector_num = 0; // total number of sectors converted so far
+        nb_sectors = total_sectors - sector_num;
+        local_progress = (float)100 /
+            (nb_sectors / MIN(nb_sectors, (IO_BUF_SIZE / 512)));
+
         for(;;) {
             nb_sectors = total_sectors - sector_num;
             if (nb_sectors <= 0) {
@@ -912,9 +931,11 @@ static int img_convert(int argc, char **argv)
                 n -= n1;
                 buf1 += n1 * 512;
             }
+            qemu_progress_print(local_progress, 100);
         }
     }
 out:
+    qemu_progress_end();
     free_option_parameters(create_options);
     free_option_parameters(param);
     qemu_free(buf);
@@ -1184,6 +1205,7 @@ static int img_rebase(int argc, char **argv)
     const char *fmt, *out_basefmt, *out_baseimg;
     int c, flags, ret;
     int unsafe = 0;
+    int progress = 0;
 
     /* Parse commandline parameters */
     fmt = NULL;
@@ -1191,7 +1213,7 @@ static int img_rebase(int argc, char **argv)
     out_basefmt = NULL;
 
     for(;;) {
-        c = getopt(argc, argv, "uhf:F:b:");
+        c = getopt(argc, argv, "uhf:F:b:p");
         if (c == -1) {
             break;
         }
@@ -1212,6 +1234,9 @@ static int img_rebase(int argc, char **argv)
         case 'u':
             unsafe = 1;
             break;
+        case 'p':
+            progress = 1;
+            break;
         }
     }
 
@@ -1220,6 +1245,9 @@ static int img_rebase(int argc, char **argv)
     }
     filename = argv[optind++];
 
+    qemu_progress_init(progress, 2.0);
+    qemu_progress_print(0, 100);
+
     /*
      * Open the images.
      *
@@ -1295,12 +1323,15 @@ static int img_rebase(int argc, char **argv)
         int n;
         uint8_t * buf_old;
         uint8_t * buf_new;
+        float local_progress;
 
         buf_old = qemu_malloc(IO_BUF_SIZE);
         buf_new = qemu_malloc(IO_BUF_SIZE);
 
         bdrv_get_geometry(bs, &num_sectors);
 
+        local_progress = (float)100 /
+            (num_sectors / MIN(num_sectors, (IO_BUF_SIZE / 512)));
         for (sector = 0; sector < num_sectors; sector += n) {
 
             /* How many sectors can we handle with the next read? */
@@ -1348,6 +1379,7 @@ static int img_rebase(int argc, char **argv)
 
                 written += pnum;
             }
+            qemu_progress_print(local_progress, 100);
         }
 
         qemu_free(buf_old);
@@ -1368,6 +1400,7 @@ static int img_rebase(int argc, char **argv)
             out_baseimg, strerror(-ret));
     }
 
+    qemu_progress_print(100, 0);
     /*
      * TODO At this point it is possible to check if any clusters that are
      * allocated in the COW file are the same in the backing file. If so, they
@@ -1375,6 +1408,7 @@ static int img_rebase(int argc, char **argv)
      * backing file, in case of a crash this would lead to corruption.
      */
 out:
+    qemu_progress_end();
     /* Cleanup */
     if (!unsafe) {
         bdrv_delete(bs_old_backing);
diff --git a/qemu-progress.c b/qemu-progress.c
new file mode 100644
index 0000000..656e065
--- /dev/null
+++ b/qemu-progress.c
@@ -0,0 +1,89 @@
+/*
+ * QEMU progress printing utility functions
+ *
+ * Copyright (C) 2011 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "osdep.h"
+#include "sysemu.h"
+#include <stdio.h>
+
+struct progress_state {
+    int enabled;
+    float current;
+    float last_print;
+    float min_skip;
+};
+
+static struct progress_state state;
+
+/*
+ * Simple progress print function.
+ * @percent relative percent of current operation
+ * @max percent of total operation
+ */
+static void progress_simple_print(void)
+{
+    if (state.enabled) {
+        printf("    (%3.2f/100%%)\r", state.current);
+        fflush(stdout);
+    }
+}
+
+static void progress_simple_end(void)
+{
+    if (state.enabled) {
+        printf("\n");
+    }
+}
+
+void qemu_progress_init(int enabled, float min_skip)
+{
+    state.enabled = enabled;
+    state.min_skip = min_skip;
+}
+
+void qemu_progress_end(void)
+{
+    progress_simple_end();
+}
+
+void qemu_progress_print(float percent, int max)
+{
+    float current;
+
+    if (max == 0) {
+        current = percent;
+    } else {
+        current = state.current + percent / 100 * max;
+    }
+    if (current > 100) {
+        current = 100;
+    }
+    state.current = current;
+
+    if (current > (state.last_print + state.min_skip) ||
+        (current == 100) || (current == 0)) {
+        state.last_print = state.current;
+        progress_simple_print();
+    }
+}
commit 46a4e4e6085c1e5ae498e350009ff6d321d9ee67
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Mar 29 20:04:41 2011 +0100

    block: Do not cache device size for removable media
    
    The block layer caches the device size to avoid doing lseek(fd, 0,
    SEEK_END) every time this value is needed.  For removable media the
    device size becomes stale if a new medium is inserted.  This patch
    simply prevents device size caching for removable media.
    
    A smarter solution is to update the cached device size when a new medium
    is inserted.  Given that there are currently bugs with CD-ROM media
    change I do not want to implement that approach until we've gotten
    things correct first.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index d8da3b0..f731c7a 100644
--- a/block.c
+++ b/block.c
@@ -1161,14 +1161,12 @@ int64_t bdrv_getlength(BlockDriverState *bs)
     if (!drv)
         return -ENOMEDIUM;
 
-    /* Fixed size devices use the total_sectors value for speed instead of
-       issuing a length query (like lseek) on each call.  Also, legacy block
-       drivers don't provide a bdrv_getlength function and must use
-       total_sectors. */
-    if (!bs->growable || !drv->bdrv_getlength) {
-        return bs->total_sectors * BDRV_SECTOR_SIZE;
-    }
-    return drv->bdrv_getlength(bs);
+    if (bs->growable || bs->removable) {
+        if (drv->bdrv_getlength) {
+            return drv->bdrv_getlength(bs);
+        }
+    }
+    return bs->total_sectors * BDRV_SECTOR_SIZE;
 }
 
 /* return 0 as number of sectors if no device present or error */
commit b8c6d0958943c96ca9401961a1200568c7ec0268
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Mar 29 20:04:40 2011 +0100

    trace: Trace bdrv_set_locked()
    
    It can be handy to know when the guest locks/unlocks the CD-ROM tray.
    This trace event makes that possible.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index c93ec6d..d8da3b0 100644
--- a/block.c
+++ b/block.c
@@ -2817,6 +2817,8 @@ void bdrv_set_locked(BlockDriverState *bs, int locked)
 {
     BlockDriver *drv = bs->drv;
 
+    trace_bdrv_set_locked(bs, locked);
+
     bs->locked = locked;
     if (drv && drv->bdrv_set_locked) {
         drv->bdrv_set_locked(bs, locked);
diff --git a/trace-events b/trace-events
index 06efdb7..703b745 100644
--- a/trace-events
+++ b/trace-events
@@ -54,6 +54,7 @@ disable bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d"
 disable bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
 disable bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
+disable bdrv_set_locked(void *bs, int locked) "bs %p locked %d"
 
 # hw/virtio-blk.c
 disable virtio_blk_req_complete(void *req, int status) "req %p status %d"
commit d22b2f41c470067758b3636a01b452dfeda7069f
Author: Ryan Harper <ryanh at us.ibm.com>
Date:   Tue Mar 29 20:51:47 2011 -0500

    Do not delete BlockDriverState when deleting the drive
    
    When removing a drive from the host-side via drive_del we currently have
    the following path:
    
    drive_del
    qemu_aio_flush()
    bdrv_close()    // zaps bs->drv, which makes any subsequent I/O get
                    // dropped.  Works as designed
    drive_uninit()
    bdrv_delete()   // frees the bs.  Since the device is still connected to
                    // bs, any subsequent I/O is a use-after-free.
    
    The value of bs->drv becomes unpredictable on free.  As long as it
    remains null, I/O still gets dropped, however it could become non-null
    at any point after the free resulting SEGVs or other QEMU state
    corruption.
    
    To resolve this issue as simply as possible, we can chose to not
    actually delete the BlockDriverState pointer.  Since bdrv_close()
    handles setting the drv pointer to NULL, we just need to remove the
    BlockDriverState from the QLIST that is used to enumerate the block
    devices.  This is currently handled within bdrv_delete, so move this
    into its own function, bdrv_make_anon().
    
    The result is that we can now invoke drive_del, this closes the file
    descriptors and sets BlockDriverState->drv to NULL which prevents futher
    IO to the device, and since we do not free BlockDriverState, we don't
    have to worry about the copy retained in the block devices.
    
    We also don't attempt to remove the qdev property since we are no longer
    deleting the BlockDriverState on drives with associated drives.  This
    also allows for removing Drives with no devices associated either.
    
    Reported-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Ryan Harper <ryanh at us.ibm.com>
    Acked-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index c8e2f97..c93ec6d 100644
--- a/block.c
+++ b/block.c
@@ -697,14 +697,22 @@ void bdrv_close_all(void)
     }
 }
 
+/* make a BlockDriverState anonymous by removing from bdrv_state list.
+   Also, NULL terminate the device_name to prevent double remove */
+void bdrv_make_anon(BlockDriverState *bs)
+{
+    if (bs->device_name[0] != '\0') {
+        QTAILQ_REMOVE(&bdrv_states, bs, list);
+    }
+    bs->device_name[0] = '\0';
+}
+
 void bdrv_delete(BlockDriverState *bs)
 {
     assert(!bs->peer);
 
     /* remove from list, if necessary */
-    if (bs->device_name[0] != '\0') {
-        QTAILQ_REMOVE(&bdrv_states, bs, list);
-    }
+    bdrv_make_anon(bs);
 
     bdrv_close(bs);
     if (bs->file != NULL) {
diff --git a/block.h b/block.h
index 5d78fc0..52e9cad 100644
--- a/block.h
+++ b/block.h
@@ -66,6 +66,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options);
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
 BlockDriverState *bdrv_new(const char *device_name);
+void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
 int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
diff --git a/blockdev.c b/blockdev.c
index bbe92fe..5429621 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -737,8 +737,6 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
     BlockDriverState *bs;
-    BlockDriverState **ptr;
-    Property *prop;
 
     bs = bdrv_find(id);
     if (!bs) {
@@ -755,24 +753,17 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     bdrv_flush(bs);
     bdrv_close(bs);
 
-    /* clean up guest state from pointing to host resource by
-     * finding and removing DeviceState "drive" property */
+    /* if we have a device associated with this BlockDriverState (bs->peer)
+     * then we need to make the drive anonymous until the device
+     * can be removed.  If this is a drive with no device backing
+     * then we can just get rid of the block driver state right here.
+     */
     if (bs->peer) {
-        for (prop = bs->peer->info->props; prop && prop->name; prop++) {
-            if (prop->info->type == PROP_TYPE_DRIVE) {
-                ptr = qdev_get_prop_ptr(bs->peer, prop);
-                if (*ptr == bs) {
-                    bdrv_detach(bs, bs->peer);
-                    *ptr = NULL;
-                    break;
-                }
-            }
-        }
+        bdrv_make_anon(bs);
+    } else {
+        drive_uninit(drive_get_by_blockdev(bs));
     }
 
-    /* clean up host side */
-    drive_uninit(drive_get_by_blockdev(bs));
-
     return 0;
 }
 
commit f6ec953ca329d4509e5a1a1ff051365fccdbb6b7
Author: Feiran Zheng <famcool at gmail.com>
Date:   Tue Mar 29 09:00:15 2011 +0800

    hw/xen_disk: ioreq not finished on error
    
    Bug fix: routines 'ioreq_runio_qemu_sync' and 'ioreq_runio_qemu_aio'
    won't call 'ioreq_unmap' or 'ioreq_finish' on errors, leaving ioreq in
    the blkdev->inflight list and a leak.
    
    Signed-off-by: Feiran Zheng <famcool at gmail.com>
    Acked-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 445bf03..558bf8a 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -310,7 +310,7 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
     off_t pos;
 
     if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
-	goto err;
+	goto err_no_map;
     if (ioreq->presync)
 	bdrv_flush(blkdev->bs);
 
@@ -364,6 +364,9 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
     return 0;
 
 err:
+    ioreq_unmap(ioreq);
+err_no_map:
+    ioreq_finish(ioreq);
     ioreq->status = BLKIF_RSP_ERROR;
     return -1;
 }
@@ -393,7 +396,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
     struct XenBlkDev *blkdev = ioreq->blkdev;
 
     if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
-	goto err;
+	goto err_no_map;
 
     ioreq->aio_inflight++;
     if (ioreq->presync)
@@ -427,6 +430,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
     return 0;
 
 err:
+    ioreq_unmap(ioreq);
+err_no_map:
+    ioreq_finish(ioreq);
     ioreq->status = BLKIF_RSP_ERROR;
     return -1;
 }
commit 3b8e6a2db1946b5f21e69fde31b39f43367f1928
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Apr 5 13:00:36 2011 +0200

    exec: Handle registrations of the entire address space
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/exec.c b/exec.c
index 964ce31..983c0db 100644
--- a/exec.c
+++ b/exec.c
@@ -2611,6 +2611,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     ram_addr_t orig_size = size;
     subpage_t *subpage;
 
+    assert(size);
     cpu_notify_set_memory(start_addr, size, phys_offset);
 
     if (phys_offset == IO_MEM_UNASSIGNED) {
@@ -2619,7 +2620,9 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     region_offset &= TARGET_PAGE_MASK;
     size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + (target_phys_addr_t)size;
-    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
+
+    addr = start_addr;
+    do {
         p = phys_page_find(addr >> TARGET_PAGE_BITS);
         if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
             ram_addr_t orig_memory = p->phys_offset;
@@ -2671,7 +2674,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
             }
         }
         region_offset += TARGET_PAGE_SIZE;
-    }
+        addr += TARGET_PAGE_SIZE;
+    } while (addr != end_addr);
 
     /* since each CPU stores ram addresses in its TLB cache, we must
        reset the modified entries */
commit 99123e139d698bee1531e8887e1a58207a52082b
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Thu Apr 7 01:12:28 2011 -0400

    configure: add --version flag
    
    Standard autoconf scripts include a --version flag so people can easily
    query things.  Add this to qemu's configure so it too can integrate with
    build systems that have standard autotool helpers.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/configure b/configure
index faaed60..ae97e11 100755
--- a/configure
+++ b/configure
@@ -494,6 +494,8 @@ for opt do
   case "$opt" in
   --help|-h) show_help=yes
   ;;
+  --version|-V) exec cat $source_path/VERSION
+  ;;
   --prefix=*) prefix="$optarg"
   ;;
   --interp-prefix=*) interp_prefix="$optarg"
commit c8f930c0eeb696d638f4d4bf654e955fa44ff40f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 4 12:09:22 2011 +0100

    cpu-all.h: Remove unnecessary target-specific ifdef for CPU_QuadU
    
    CPU_QuadU isn't used on all targets, but there's no harm in defining the
    typedef anyway. It only needs to be guarded by CONFIG_SOFTFLOAT, because
    softfloat-native doesn't have a float128 type. This avoids the need for
    every new target which uses CPU_QuadU to add itself to an #ifdef in
    what ought to be target-agnostic code.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-all.h b/cpu-all.h
index 4cc445f..dc0f2f0 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -138,11 +138,10 @@ typedef union {
     uint64_t ll;
 } CPU_DoubleU;
 
-#if defined(TARGET_SPARC) || defined(TARGET_S390X)
+#if defined(CONFIG_SOFTFLOAT)
 typedef union {
     float128 q;
-#if defined(HOST_WORDS_BIGENDIAN) \
-    || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
+#if defined(HOST_WORDS_BIGENDIAN)
     struct {
         uint32_t upmost;
         uint32_t upper;
commit cc49f2178041d5754368d4b62cb56b735aafbe9f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 4 11:46:35 2011 +0100

    target-arm: Make Neon helper routines use correct FP status
    
    Make the Neon helper routines use the correct FP status from
    the CPUEnv rather than using a dummy static one. This means
    they will correctly handle denormals and NaNs and will set
    FPSCR exception bits properly.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 315e693..c3ac96a 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -18,8 +18,7 @@
 
 #define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] = CPSR_Q
 
-static float_status neon_float_status;
-#define NFS &neon_float_status
+#define NFS (&env->vfp.standard_fp_status)
 
 #define NEON_TYPE1(name, type) \
 typedef struct \
commit 947a2fa21b61703802a660a938cabd7b3600ee79
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 4 11:46:34 2011 +0100

    target-arm: Use global env in iwmmxt_helper.c helpers
    
    Use the global 'env' variable in the helper functions in iwmmxt_helper.c.
    This means we don't need to pass env as an argument to them any more.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 0705b9c..ae701e8 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -375,47 +375,47 @@ DEF_HELPER_2(iwmmxt_macsw, i64, i64, i64)
 DEF_HELPER_2(iwmmxt_macuw, i64, i64, i64)
 DEF_HELPER_1(iwmmxt_setpsr_nz, i32, i64)
 
-#define DEF_IWMMXT_HELPER_SIZE_ENV(name) \
-DEF_HELPER_3(iwmmxt_##name##b, i64, env, i64, i64) \
-DEF_HELPER_3(iwmmxt_##name##w, i64, env, i64, i64) \
-DEF_HELPER_3(iwmmxt_##name##l, i64, env, i64, i64) \
-
-DEF_IWMMXT_HELPER_SIZE_ENV(unpackl)
-DEF_IWMMXT_HELPER_SIZE_ENV(unpackh)
-
-DEF_HELPER_2(iwmmxt_unpacklub, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackluw, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpacklul, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhub, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhuw, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhul, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpacklsb, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpacklsw, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpacklsl, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhsb, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhsw, i64, env, i64)
-DEF_HELPER_2(iwmmxt_unpackhsl, i64, env, i64)
-
-DEF_IWMMXT_HELPER_SIZE_ENV(cmpeq)
-DEF_IWMMXT_HELPER_SIZE_ENV(cmpgtu)
-DEF_IWMMXT_HELPER_SIZE_ENV(cmpgts)
-
-DEF_IWMMXT_HELPER_SIZE_ENV(mins)
-DEF_IWMMXT_HELPER_SIZE_ENV(minu)
-DEF_IWMMXT_HELPER_SIZE_ENV(maxs)
-DEF_IWMMXT_HELPER_SIZE_ENV(maxu)
-
-DEF_IWMMXT_HELPER_SIZE_ENV(subn)
-DEF_IWMMXT_HELPER_SIZE_ENV(addn)
-DEF_IWMMXT_HELPER_SIZE_ENV(subu)
-DEF_IWMMXT_HELPER_SIZE_ENV(addu)
-DEF_IWMMXT_HELPER_SIZE_ENV(subs)
-DEF_IWMMXT_HELPER_SIZE_ENV(adds)
-
-DEF_HELPER_3(iwmmxt_avgb0, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_avgb1, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_avgw0, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_avgw1, i64, env, i64, i64)
+#define DEF_IWMMXT_HELPER_SIZE(name) \
+DEF_HELPER_2(iwmmxt_##name##b, i64, i64, i64) \
+DEF_HELPER_2(iwmmxt_##name##w, i64, i64, i64) \
+DEF_HELPER_2(iwmmxt_##name##l, i64, i64, i64) \
+
+DEF_IWMMXT_HELPER_SIZE(unpackl)
+DEF_IWMMXT_HELPER_SIZE(unpackh)
+
+DEF_HELPER_1(iwmmxt_unpacklub, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackluw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklul, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhub, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhuw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhul, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsb, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpacklsl, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsb, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsw, i64, i64)
+DEF_HELPER_1(iwmmxt_unpackhsl, i64, i64)
+
+DEF_IWMMXT_HELPER_SIZE(cmpeq)
+DEF_IWMMXT_HELPER_SIZE(cmpgtu)
+DEF_IWMMXT_HELPER_SIZE(cmpgts)
+
+DEF_IWMMXT_HELPER_SIZE(mins)
+DEF_IWMMXT_HELPER_SIZE(minu)
+DEF_IWMMXT_HELPER_SIZE(maxs)
+DEF_IWMMXT_HELPER_SIZE(maxu)
+
+DEF_IWMMXT_HELPER_SIZE(subn)
+DEF_IWMMXT_HELPER_SIZE(addn)
+DEF_IWMMXT_HELPER_SIZE(subu)
+DEF_IWMMXT_HELPER_SIZE(addu)
+DEF_IWMMXT_HELPER_SIZE(subs)
+DEF_IWMMXT_HELPER_SIZE(adds)
+
+DEF_HELPER_2(iwmmxt_avgb0, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgb1, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgw0, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_avgw1, i64, i64, i64)
 
 DEF_HELPER_2(iwmmxt_msadb, i64, i64, i64)
 
@@ -434,26 +434,26 @@ DEF_HELPER_1(iwmmxt_msbb, i32, i64)
 DEF_HELPER_1(iwmmxt_msbw, i32, i64)
 DEF_HELPER_1(iwmmxt_msbl, i32, i64)
 
-DEF_HELPER_3(iwmmxt_srlw, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_srll, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_srlq, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_sllw, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_slll, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_sllq, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_sraw, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_sral, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_sraq, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_rorw, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_rorl, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_rorq, i64, env, i64, i32)
-DEF_HELPER_3(iwmmxt_shufh, i64, env, i64, i32)
-
-DEF_HELPER_3(iwmmxt_packuw, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_packul, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_packuq, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_packsw, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_packsl, i64, env, i64, i64)
-DEF_HELPER_3(iwmmxt_packsq, i64, env, i64, i64)
+DEF_HELPER_2(iwmmxt_srlw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_srll, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_srlq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sllw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_slll, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sllq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sraw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sral, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_sraq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorw, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorl, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_rorq, i64, i64, i32)
+DEF_HELPER_2(iwmmxt_shufh, i64, i64, i32)
+
+DEF_HELPER_2(iwmmxt_packuw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packul, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packuq, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsw, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsl, i64, i64, i64)
+DEF_HELPER_2(iwmmxt_packsq, i64, i64, i64)
 
 DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
 DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c
index 3332f70..3941f1f 100644
--- a/target-arm/iwmmxt_helper.c
+++ b/target-arm/iwmmxt_helper.c
@@ -23,7 +23,7 @@
 #include <stdio.h>
 
 #include "cpu.h"
-#include "exec-all.h"
+#include "exec.h"
 #include "helpers.h"
 
 /* iwMMXt macros extracted from GNU gdb.  */
@@ -162,8 +162,7 @@ uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
     SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
     SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
 #define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)			\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUState *env, \
-                                                 uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xff) << 0) | (((b >> SH0) & 0xff) << 8) |	\
@@ -177,8 +176,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, b)))(CPUState *env, \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUState *env, \
-                                        uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xffff) << 0) |				\
@@ -190,8 +188,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, w)))(CPUState *env, \
         NZBIT8(a >> 32, 2) | NZBIT8(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUState *env, \
-                                        uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(uint64_t a, uint64_t b) \
 {								\
     a =							        \
         (((a >> SH0) & 0xffffffff) << 0) |			\
@@ -200,8 +197,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, l)))(CPUState *env, \
         NZBIT32(a >> 0, 0) | NZBIT32(a >> 32, 1);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(uint64_t x)   \
 {								\
     x =							        \
         (((x >> SH0) & 0xff) << 0) |				\
@@ -213,8 +209,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ub)))(CPUState *env, \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(uint64_t x)   \
 {								\
     x =							        \
         (((x >> SH0) & 0xffff) << 0) |				\
@@ -223,15 +218,13 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, uw)))(CPUState *env, \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, ul)))(uint64_t x)   \
 {								\
     x = (((x >> SH0) & 0xffffffff) << 0);			\
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);	\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(uint64_t x)   \
 {								\
     x =							        \
         ((uint64_t) EXTEND8H((x >> SH0) & 0xff) << 0) |	        \
@@ -243,8 +236,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sb)))(CPUState *env, \
         NZBIT16(x >> 32, 2) | NZBIT16(x >> 48, 3);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(uint64_t x)   \
 {								\
     x =							        \
         ((uint64_t) EXTEND16((x >> SH0) & 0xffff) << 0) |	\
@@ -253,8 +245,7 @@ uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sw)))(CPUState *env, \
         NZBIT32(x >> 0, 0) | NZBIT32(x >> 32, 1);		\
     return x;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(CPUState *env, \
-                                                  uint64_t x)   \
+uint64_t HELPER(glue(iwmmxt_unpack, glue(S, sl)))(uint64_t x)   \
 {								\
     x = EXTEND32((x >> SH0) & 0xffffffff);			\
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x >> 0);	\
@@ -264,8 +255,7 @@ IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
 IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
 
 #define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)			\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUState *env,    \
-                                        uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(uint64_t a, uint64_t b) \
 {								\
     a =							        \
         CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |		\
@@ -279,8 +269,7 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, b)))(CPUState *env,    \
         NZBIT8(a >> 48, 6) | NZBIT8(a >> 56, 7);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUState *env,    \
-                                        uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |	\
         CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);	\
@@ -289,8 +278,7 @@ uint64_t HELPER(glue(iwmmxt_, glue(SUFF, w)))(CPUState *env,    \
         NZBIT16(a >> 32, 2) | NZBIT16(a >> 48, 3);		\
     return a;                                                   \
 }								\
-uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(CPUState *env,    \
-                                        uint64_t a, uint64_t b) \
+uint64_t HELPER(glue(iwmmxt_, glue(SUFF, l)))(uint64_t a, uint64_t b) \
 {								\
     a = CMP(0, Tl, O, 0xffffffff) |				\
         CMP(32, Tl, O, 0xffffffff);				\
@@ -329,7 +317,7 @@ IWMMXT_OP_CMP(adds, int8_t, int16_t, int32_t, +)
 #define AVGB(SHR) ((( \
         ((a >> SHR) & 0xff) + ((b >> SHR) & 0xff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGB(r)                                                 \
-uint64_t HELPER(iwmmxt_avgb##r)(CPUState *env, uint64_t a, uint64_t b)    \
+uint64_t HELPER(iwmmxt_avgb##r)(uint64_t a, uint64_t b)                   \
 {                                                                         \
     const int round = r;                                                  \
     a = AVGB(0) | AVGB(8) | AVGB(16) | AVGB(24) |                         \
@@ -353,7 +341,7 @@ IWMMXT_OP_AVGB(1)
 #define AVGW(SHR) ((( \
         ((a >> SHR) & 0xffff) + ((b >> SHR) & 0xffff) + round) >> 1) << SHR)
 #define IWMMXT_OP_AVGW(r)                                               \
-uint64_t HELPER(iwmmxt_avgw##r)(CPUState *env, uint64_t a, uint64_t b)  \
+uint64_t HELPER(iwmmxt_avgw##r)(uint64_t a, uint64_t b)                 \
 {                                                                       \
     const int round = r;                                                \
     a = AVGW(0) | AVGW(16) | AVGW(32) | AVGW(48);                       \
@@ -464,7 +452,7 @@ uint32_t HELPER(iwmmxt_msbl)(uint64_t x)
 }
 
 /* FIXME: Split wCASF setting into a separate op to avoid env use.  */
-uint64_t HELPER(iwmmxt_srlw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlw)(uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) >> n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) >> n) & (0xffffll << 16)) |
@@ -476,7 +464,7 @@ uint64_t HELPER(iwmmxt_srlw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srll)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srll)(uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32));
@@ -485,14 +473,14 @@ uint64_t HELPER(iwmmxt_srll)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_srlq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_srlq)(uint64_t x, uint32_t n)
 {
     x >>= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllw)(uint64_t x, uint32_t n)
 {
     x = (((x & (0xffffll << 0)) << n) & (0xffffll << 0)) |
         (((x & (0xffffll << 16)) << n) & (0xffffll << 16)) |
@@ -504,7 +492,7 @@ uint64_t HELPER(iwmmxt_sllw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_slll)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_slll)(uint64_t x, uint32_t n)
 {
     x = ((x << n) & (0xffffffffll << 0)) |
         ((x & (0xffffffffll << 32)) << n);
@@ -513,14 +501,14 @@ uint64_t HELPER(iwmmxt_slll)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sllq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sllq)(uint64_t x, uint32_t n)
 {
     x <<= n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraw)(uint64_t x, uint32_t n)
 {
     x = ((uint64_t) ((EXTEND16(x >> 0) >> n) & 0xffff) << 0) |
         ((uint64_t) ((EXTEND16(x >> 16) >> n) & 0xffff) << 16) |
@@ -532,7 +520,7 @@ uint64_t HELPER(iwmmxt_sraw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sral)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sral)(uint64_t x, uint32_t n)
 {
     x = (((EXTEND32(x >> 0) >> n) & 0xffffffff) << 0) |
         (((EXTEND32(x >> 32) >> n) & 0xffffffff) << 32);
@@ -541,14 +529,14 @@ uint64_t HELPER(iwmmxt_sral)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_sraq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_sraq)(uint64_t x, uint32_t n)
 {
     x = (int64_t) x >> n;
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorw)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorw)(uint64_t x, uint32_t n)
 {
     x = ((((x & (0xffffll << 0)) >> n) |
           ((x & (0xffffll << 0)) << (16 - n))) & (0xffffll << 0)) |
@@ -564,7 +552,7 @@ uint64_t HELPER(iwmmxt_rorw)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorl)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorl)(uint64_t x, uint32_t n)
 {
     x = ((x & (0xffffffffll << 0)) >> n) |
         ((x >> n) & (0xffffffffll << 32)) |
@@ -575,14 +563,14 @@ uint64_t HELPER(iwmmxt_rorl)(CPUState *env, uint64_t x, uint32_t n)
     return x;
 }
 
-uint64_t HELPER(iwmmxt_rorq)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_rorq)(uint64_t x, uint32_t n)
 {
     x = (x >> n) | (x << (64 - n));
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x);
     return x;
 }
 
-uint64_t HELPER(iwmmxt_shufh)(CPUState *env, uint64_t x, uint32_t n)
+uint64_t HELPER(iwmmxt_shufh)(uint64_t x, uint32_t n)
 {
     x = (((x >> ((n << 4) & 0x30)) & 0xffff) << 0) |
         (((x >> ((n << 2) & 0x30)) & 0xffff) << 16) |
@@ -595,7 +583,7 @@ uint64_t HELPER(iwmmxt_shufh)(CPUState *env, uint64_t x, uint32_t n)
 }
 
 /* TODO: Unsigned-Saturation */
-uint64_t HELPER(iwmmxt_packuw)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuw)(uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -609,7 +597,7 @@ uint64_t HELPER(iwmmxt_packuw)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packul)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packul)(uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -619,7 +607,7 @@ uint64_t HELPER(iwmmxt_packul)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packuq)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packuq)(uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
@@ -628,7 +616,7 @@ uint64_t HELPER(iwmmxt_packuq)(CPUState *env, uint64_t a, uint64_t b)
 }
 
 /* TODO: Signed-Saturation */
-uint64_t HELPER(iwmmxt_packsw)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsw)(uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xff) << 0) | (((a >> 16) & 0xff) << 8) |
         (((a >> 32) & 0xff) << 16) | (((a >> 48) & 0xff) << 24) |
@@ -642,7 +630,7 @@ uint64_t HELPER(iwmmxt_packsw)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsl)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsl)(uint64_t a, uint64_t b)
 {
     a = (((a >> 0) & 0xffff) << 0) | (((a >> 32) & 0xffff) << 16) |
         (((b >> 0) & 0xffff) << 32) | (((b >> 32) & 0xffff) << 48);
@@ -652,7 +640,7 @@ uint64_t HELPER(iwmmxt_packsl)(CPUState *env, uint64_t a, uint64_t b)
     return a;
 }
 
-uint64_t HELPER(iwmmxt_packsq)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(iwmmxt_packsq)(uint64_t a, uint64_t b)
 {
     a = (a & 0xffffffff) | ((b & 0xffffffff) << 32);
     env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 53c40ac..c6cb39a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -1159,22 +1159,15 @@ static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
     gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
 }
 
-#define IWMMXT_OP_ENV(name) \
-static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
-{ \
-    iwmmxt_load_reg(cpu_V1, rn); \
-    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
-}
-
-#define IWMMXT_OP_ENV_SIZE(name) \
-IWMMXT_OP_ENV(name##b) \
-IWMMXT_OP_ENV(name##w) \
-IWMMXT_OP_ENV(name##l)
+#define IWMMXT_OP_SIZE(name) \
+IWMMXT_OP(name##b) \
+IWMMXT_OP(name##w) \
+IWMMXT_OP(name##l)
 
-#define IWMMXT_OP_ENV1(name) \
+#define IWMMXT_OP_1(name) \
 static inline void gen_op_iwmmxt_##name##_M0(void) \
 { \
-    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
+    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \
 }
 
 IWMMXT_OP(maddsq)
@@ -1188,51 +1181,51 @@ IWMMXT_OP(muluhw)
 IWMMXT_OP(macsw)
 IWMMXT_OP(macuw)
 
-IWMMXT_OP_ENV_SIZE(unpackl)
-IWMMXT_OP_ENV_SIZE(unpackh)
-
-IWMMXT_OP_ENV1(unpacklub)
-IWMMXT_OP_ENV1(unpackluw)
-IWMMXT_OP_ENV1(unpacklul)
-IWMMXT_OP_ENV1(unpackhub)
-IWMMXT_OP_ENV1(unpackhuw)
-IWMMXT_OP_ENV1(unpackhul)
-IWMMXT_OP_ENV1(unpacklsb)
-IWMMXT_OP_ENV1(unpacklsw)
-IWMMXT_OP_ENV1(unpacklsl)
-IWMMXT_OP_ENV1(unpackhsb)
-IWMMXT_OP_ENV1(unpackhsw)
-IWMMXT_OP_ENV1(unpackhsl)
-
-IWMMXT_OP_ENV_SIZE(cmpeq)
-IWMMXT_OP_ENV_SIZE(cmpgtu)
-IWMMXT_OP_ENV_SIZE(cmpgts)
-
-IWMMXT_OP_ENV_SIZE(mins)
-IWMMXT_OP_ENV_SIZE(minu)
-IWMMXT_OP_ENV_SIZE(maxs)
-IWMMXT_OP_ENV_SIZE(maxu)
-
-IWMMXT_OP_ENV_SIZE(subn)
-IWMMXT_OP_ENV_SIZE(addn)
-IWMMXT_OP_ENV_SIZE(subu)
-IWMMXT_OP_ENV_SIZE(addu)
-IWMMXT_OP_ENV_SIZE(subs)
-IWMMXT_OP_ENV_SIZE(adds)
-
-IWMMXT_OP_ENV(avgb0)
-IWMMXT_OP_ENV(avgb1)
-IWMMXT_OP_ENV(avgw0)
-IWMMXT_OP_ENV(avgw1)
+IWMMXT_OP_SIZE(unpackl)
+IWMMXT_OP_SIZE(unpackh)
+
+IWMMXT_OP_1(unpacklub)
+IWMMXT_OP_1(unpackluw)
+IWMMXT_OP_1(unpacklul)
+IWMMXT_OP_1(unpackhub)
+IWMMXT_OP_1(unpackhuw)
+IWMMXT_OP_1(unpackhul)
+IWMMXT_OP_1(unpacklsb)
+IWMMXT_OP_1(unpacklsw)
+IWMMXT_OP_1(unpacklsl)
+IWMMXT_OP_1(unpackhsb)
+IWMMXT_OP_1(unpackhsw)
+IWMMXT_OP_1(unpackhsl)
+
+IWMMXT_OP_SIZE(cmpeq)
+IWMMXT_OP_SIZE(cmpgtu)
+IWMMXT_OP_SIZE(cmpgts)
+
+IWMMXT_OP_SIZE(mins)
+IWMMXT_OP_SIZE(minu)
+IWMMXT_OP_SIZE(maxs)
+IWMMXT_OP_SIZE(maxu)
+
+IWMMXT_OP_SIZE(subn)
+IWMMXT_OP_SIZE(addn)
+IWMMXT_OP_SIZE(subu)
+IWMMXT_OP_SIZE(addu)
+IWMMXT_OP_SIZE(subs)
+IWMMXT_OP_SIZE(adds)
+
+IWMMXT_OP(avgb0)
+IWMMXT_OP(avgb1)
+IWMMXT_OP(avgw0)
+IWMMXT_OP(avgw1)
 
 IWMMXT_OP(msadb)
 
-IWMMXT_OP_ENV(packuw)
-IWMMXT_OP_ENV(packul)
-IWMMXT_OP_ENV(packuq)
-IWMMXT_OP_ENV(packsw)
-IWMMXT_OP_ENV(packsl)
-IWMMXT_OP_ENV(packsq)
+IWMMXT_OP(packuw)
+IWMMXT_OP(packul)
+IWMMXT_OP(packuq)
+IWMMXT_OP(packsw)
+IWMMXT_OP(packsl)
+IWMMXT_OP(packsq)
 
 static void gen_op_iwmmxt_set_mup(void)
 {
@@ -1966,13 +1959,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -1994,13 +1987,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2022,13 +2015,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         switch ((insn >> 22) & 3) {
         case 1:
-            gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp);
             break;
         case 2:
-            gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp);
             break;
         case 3:
-            gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2050,21 +2043,21 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp);
             break;
         case 2:
             if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp);
             break;
         case 3:
             if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
                 tcg_temp_free_i32(tmp);
                 return 1;
             }
-            gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
+            gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp);
             break;
         }
         tcg_temp_free_i32(tmp);
@@ -2198,7 +2191,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
         tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
-        gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
+        gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp);
         tcg_temp_free(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
commit 2a3f75b42ac255be09ec2939b96c549ec830efd3
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 4 11:46:33 2011 +0100

    target-arm: Use global env in neon_helper.c helpers
    
    Use the global 'env' variable in the helper functions in neon_helper.c.
    This means we don't need to pass env as an argument to them any more.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 9de10e3..0705b9c 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -154,22 +154,22 @@ DEF_HELPER_2(sar_cc, i32, i32, i32)
 DEF_HELPER_2(ror_cc, i32, i32, i32)
 
 /* neon_helper.c */
-DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_u16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_u32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_s32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_u8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_s8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_u16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_u32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qsub_s32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qadd_u64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qadd_s64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qsub_u64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qsub_s64, i64, env, i64, i64)
+DEF_HELPER_2(neon_qadd_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qsub_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qadd_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qadd_s64, i64, i64, i64)
+DEF_HELPER_2(neon_qsub_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qsub_s64, i64, i64, i64)
 
 DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
 DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
@@ -247,26 +247,26 @@ DEF_HELPER_2(neon_rshl_u32, i32, i32, i32)
 DEF_HELPER_2(neon_rshl_s32, i32, i32, i32)
 DEF_HELPER_2(neon_rshl_u64, i64, i64, i64)
 DEF_HELPER_2(neon_rshl_s64, i64, i64, i64)
-DEF_HELPER_3(neon_qshl_u8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_s8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_u16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_u32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_s32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qshl_u64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qshl_s64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qshlu_s8, i32, env, i32, i32);
-DEF_HELPER_3(neon_qshlu_s16, i32, env, i32, i32);
-DEF_HELPER_3(neon_qshlu_s32, i32, env, i32, i32);
-DEF_HELPER_3(neon_qshlu_s64, i64, env, i64, i64);
-DEF_HELPER_3(neon_qrshl_u8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_s8, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_u16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_u32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_s32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrshl_u64, i64, env, i64, i64)
-DEF_HELPER_3(neon_qrshl_s64, i64, env, i64, i64)
+DEF_HELPER_2(neon_qshl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qshl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qshl_s64, i64, i64, i64)
+DEF_HELPER_2(neon_qshlu_s8, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s16, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s32, i32, i32, i32);
+DEF_HELPER_2(neon_qshlu_s64, i64, i64, i64);
+DEF_HELPER_2(neon_qrshl_u8, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s8, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u16, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u32, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qrshl_u64, i64, i64, i64)
+DEF_HELPER_2(neon_qrshl_s64, i64, i64, i64)
 
 DEF_HELPER_2(neon_add_u8, i32, i32, i32)
 DEF_HELPER_2(neon_add_u16, i32, i32, i32)
@@ -295,22 +295,22 @@ DEF_HELPER_1(neon_cls_s16, i32, i32)
 DEF_HELPER_1(neon_cls_s32, i32, i32)
 DEF_HELPER_1(neon_cnt_u8, i32, i32)
 
-DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
-DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
-DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
+DEF_HELPER_2(neon_qdmulh_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qrdmulh_s16, i32, i32, i32)
+DEF_HELPER_2(neon_qdmulh_s32, i32, i32, i32)
+DEF_HELPER_2(neon_qrdmulh_s32, i32, i32, i32)
 
 DEF_HELPER_1(neon_narrow_u8, i32, i64)
 DEF_HELPER_1(neon_narrow_u16, i32, i64)
-DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64)
-DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64)
-DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64)
-DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64)
+DEF_HELPER_1(neon_unarrow_sat8, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u8, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s8, i32, i64)
+DEF_HELPER_1(neon_unarrow_sat16, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u16, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s16, i32, i64)
+DEF_HELPER_1(neon_unarrow_sat32, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_u32, i32, i64)
+DEF_HELPER_1(neon_narrow_sat_s32, i32, i64)
 DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
 DEF_HELPER_1(neon_narrow_high_u16, i32, i64)
 DEF_HELPER_1(neon_narrow_round_high_u8, i32, i64)
@@ -326,8 +326,8 @@ DEF_HELPER_2(neon_paddl_u16, i64, i64, i64)
 DEF_HELPER_2(neon_paddl_u32, i64, i64, i64)
 DEF_HELPER_2(neon_subl_u16, i64, i64, i64)
 DEF_HELPER_2(neon_subl_u32, i64, i64, i64)
-DEF_HELPER_3(neon_addl_saturate_s32, i64, env, i64, i64)
-DEF_HELPER_3(neon_addl_saturate_s64, i64, env, i64, i64)
+DEF_HELPER_2(neon_addl_saturate_s32, i64, i64, i64)
+DEF_HELPER_2(neon_addl_saturate_s64, i64, i64, i64)
 DEF_HELPER_2(neon_abdl_u16, i64, i32, i32)
 DEF_HELPER_2(neon_abdl_s16, i64, i32, i32)
 DEF_HELPER_2(neon_abdl_u32, i64, i32, i32)
@@ -343,12 +343,12 @@ DEF_HELPER_1(neon_negl_u16, i64, i64)
 DEF_HELPER_1(neon_negl_u32, i64, i64)
 DEF_HELPER_1(neon_negl_u64, i64, i64)
 
-DEF_HELPER_2(neon_qabs_s8, i32, env, i32)
-DEF_HELPER_2(neon_qabs_s16, i32, env, i32)
-DEF_HELPER_2(neon_qabs_s32, i32, env, i32)
-DEF_HELPER_2(neon_qneg_s8, i32, env, i32)
-DEF_HELPER_2(neon_qneg_s16, i32, env, i32)
-DEF_HELPER_2(neon_qneg_s32, i32, env, i32)
+DEF_HELPER_1(neon_qabs_s8, i32, i32)
+DEF_HELPER_1(neon_qabs_s16, i32, i32)
+DEF_HELPER_1(neon_qabs_s32, i32, i32)
+DEF_HELPER_1(neon_qneg_s8, i32, i32)
+DEF_HELPER_1(neon_qneg_s16, i32, i32)
+DEF_HELPER_1(neon_qneg_s32, i32, i32)
 
 DEF_HELPER_2(neon_min_f32, i32, i32, i32)
 DEF_HELPER_2(neon_max_f32, i32, i32, i32)
@@ -461,15 +461,15 @@ DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 
 DEF_HELPER_2(set_teecr, void, env, i32)
 
-DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
-DEF_HELPER_3(neon_zip8, void, env, i32, i32)
-DEF_HELPER_3(neon_zip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
-DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
+DEF_HELPER_2(neon_unzip8, void, i32, i32)
+DEF_HELPER_2(neon_unzip16, void, i32, i32)
+DEF_HELPER_2(neon_qunzip8, void, i32, i32)
+DEF_HELPER_2(neon_qunzip16, void, i32, i32)
+DEF_HELPER_2(neon_qunzip32, void, i32, i32)
+DEF_HELPER_2(neon_zip8, void, i32, i32)
+DEF_HELPER_2(neon_zip16, void, i32, i32)
+DEF_HELPER_2(neon_qzip8, void, i32, i32)
+DEF_HELPER_2(neon_qzip16, void, i32, i32)
+DEF_HELPER_2(neon_qzip32, void, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 71f1a7e..315e693 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -10,7 +10,7 @@
 #include <stdio.h>
 
 #include "cpu.h"
-#include "exec-all.h"
+#include "exec.h"
 #include "helpers.h"
 
 #define SIGNBIT (uint32_t)0x80000000
@@ -116,10 +116,6 @@ NEON_TYPE1(u32, uint32_t)
 uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \
 NEON_VOP_BODY(vtype, n)
 
-#define NEON_VOP_ENV(name, vtype, n) \
-uint32_t HELPER(glue(neon_,name))(CPUState *env, uint32_t arg1, uint32_t arg2) \
-NEON_VOP_BODY(vtype, n)
-
 /* Pairwise operations.  */
 /* For 32-bit elements each segment only contains a single element, so
    the elementwise and pairwise operations are the same.  */
@@ -168,14 +164,14 @@ uint32_t HELPER(glue(neon_,name))(uint32_t arg) \
         dest = tmp; \
     }} while(0)
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
-NEON_VOP_ENV(qadd_u8, neon_u8, 4)
+NEON_VOP(qadd_u8, neon_u8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
-NEON_VOP_ENV(qadd_u16, neon_u16, 2)
+NEON_VOP(qadd_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_u32)(uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (res < a) {
@@ -185,7 +181,7 @@ uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_u64)(uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -210,14 +206,14 @@ uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
     dest = tmp; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
-NEON_VOP_ENV(qadd_s8, neon_s8, 4)
+NEON_VOP(qadd_s8, neon_s8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
-NEON_VOP_ENV(qadd_s16, neon_s16, 2)
+NEON_VOP(qadd_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qadd_s32)(uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
     if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
@@ -227,7 +223,7 @@ uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qadd_s64)(uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -248,14 +244,14 @@ uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
         dest = tmp; \
     }} while(0)
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
-NEON_VOP_ENV(qsub_u8, neon_u8, 4)
+NEON_VOP(qsub_u8, neon_u8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
-NEON_VOP_ENV(qsub_u16, neon_u16, 2)
+NEON_VOP(qsub_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
-uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_u32)(uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (res > a) {
@@ -265,7 +261,7 @@ uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_u64)(uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -291,14 +287,14 @@ uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
     dest = tmp; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
-NEON_VOP_ENV(qsub_s8, neon_s8, 4)
+NEON_VOP(qsub_s8, neon_s8, 4)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
-NEON_VOP_ENV(qsub_s16, neon_s16, 2)
+NEON_VOP(qsub_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
-uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
+uint32_t HELPER(neon_qsub_s32)(uint32_t a, uint32_t b)
 {
     uint32_t res = a - b;
     if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
@@ -308,7 +304,7 @@ uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
     return res;
 }
 
-uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+uint64_t HELPER(neon_qsub_s64)(uint64_t src1, uint64_t src2)
 {
     uint64_t res;
 
@@ -659,12 +655,12 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
             dest = ~0; \
         } \
     }} while (0)
-NEON_VOP_ENV(qshl_u8, neon_u8, 4)
-NEON_VOP_ENV(qshl_u16, neon_u16, 2)
-NEON_VOP_ENV(qshl_u32, neon_u32, 1)
+NEON_VOP(qshl_u8, neon_u8, 4)
+NEON_VOP(qshl_u16, neon_u16, 2)
+NEON_VOP(qshl_u32, neon_u32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_u64)(uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -714,12 +710,12 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP_ENV(qshl_s8, neon_s8, 4)
-NEON_VOP_ENV(qshl_s16, neon_s16, 2)
-NEON_VOP_ENV(qshl_s32, neon_s32, 1)
+NEON_VOP(qshl_s8, neon_s8, 4)
+NEON_VOP(qshl_s16, neon_s16, 2)
+NEON_VOP(qshl_s32, neon_s32, 1)
 #undef NEON_FN
 
-uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshl_s64)(uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -769,26 +765,26 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP_ENV(qshlu_s8, neon_u8, 4)
-NEON_VOP_ENV(qshlu_s16, neon_u16, 2)
+NEON_VOP(qshlu_s8, neon_u8, 4)
+NEON_VOP(qshlu_s16, neon_u16, 2)
 #undef NEON_FN
 
-uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qshlu_s32)(uint32_t valop, uint32_t shiftop)
 {
     if ((int32_t)valop < 0) {
         SET_QC();
         return 0;
     }
-    return helper_neon_qshl_u32(env, valop, shiftop);
+    return helper_neon_qshl_u32(valop, shiftop);
 }
 
-uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qshlu_s64)(uint64_t valop, uint64_t shiftop)
 {
     if ((int64_t)valop < 0) {
         SET_QC();
         return 0;
     }
-    return helper_neon_qshl_u64(env, valop, shiftop);
+    return helper_neon_qshl_u64(valop, shiftop);
 }
 
 /* FIXME: This is wrong.  */
@@ -815,13 +811,13 @@ uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
             dest = ~0; \
         } \
     }} while (0)
-NEON_VOP_ENV(qrshl_u8, neon_u8, 4)
-NEON_VOP_ENV(qrshl_u16, neon_u16, 2)
+NEON_VOP(qrshl_u8, neon_u8, 4)
+NEON_VOP(qrshl_u16, neon_u16, 2)
 #undef NEON_FN
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_u32)(uint32_t val, uint32_t shiftop)
 {
     uint32_t dest;
     int8_t shift = (int8_t)shiftop;
@@ -851,7 +847,7 @@ uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_u64)(uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift >= 64) {
@@ -912,13 +908,13 @@ uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
             } \
         } \
     }} while (0)
-NEON_VOP_ENV(qrshl_s8, neon_s8, 4)
-NEON_VOP_ENV(qrshl_s16, neon_s16, 2)
+NEON_VOP(qrshl_s8, neon_s8, 4)
+NEON_VOP(qrshl_s16, neon_s16, 2)
 #undef NEON_FN
 
 /* The addition of the rounding constant may overflow, so we use an
  * intermediate 64 bits accumulator.  */
-uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+uint32_t HELPER(neon_qrshl_s32)(uint32_t valop, uint32_t shiftop)
 {
     int32_t dest;
     int32_t val = (int32_t)valop;
@@ -947,7 +943,7 @@ uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
 
 /* Handling addition overflow with 64 bits inputs values is more
  * tricky than with 32 bits values.  */
-uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+uint64_t HELPER(neon_qrshl_s64)(uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
@@ -1156,10 +1152,10 @@ uint32_t HELPER(neon_cnt_u8)(uint32_t x)
     dest = tmp >> 16; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 0)
-NEON_VOP_ENV(qdmulh_s16, neon_s16, 2)
+NEON_VOP(qdmulh_s16, neon_s16, 2)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 1)
-NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2)
+NEON_VOP(qrdmulh_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_QDMULH16
 
@@ -1182,10 +1178,10 @@ NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2)
     dest = tmp >> 32; \
     } while(0)
 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 0)
-NEON_VOP_ENV(qdmulh_s32, neon_s32, 1)
+NEON_VOP(qdmulh_s32, neon_s32, 1)
 #undef NEON_FN
 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 1)
-NEON_VOP_ENV(qrdmulh_s32, neon_s32, 1)
+NEON_VOP(qrdmulh_s32, neon_s32, 1)
 #undef NEON_FN
 #undef NEON_QDMULH32
 
@@ -1226,7 +1222,7 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
 }
 
-uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat8)(uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1253,7 +1249,7 @@ uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u8)(uint64_t x)
 {
     uint16_t s;
     uint8_t d;
@@ -1276,7 +1272,7 @@ uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s8)(uint64_t x)
 {
     int16_t s;
     uint8_t d;
@@ -1299,7 +1295,7 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
     return res;
 }
 
-uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat16)(uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1322,7 +1318,7 @@ uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u16)(uint64_t x)
 {
     uint32_t high;
     uint32_t low;
@@ -1339,7 +1335,7 @@ uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
     return low | (high << 16);
 }
 
-uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s16)(uint64_t x)
 {
     int32_t low;
     int32_t high;
@@ -1356,7 +1352,7 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
     return (uint16_t)low | (high << 16);
 }
 
-uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_unarrow_sat32)(uint64_t x)
 {
     if (x & 0x8000000000000000ull) {
         SET_QC();
@@ -1369,7 +1365,7 @@ uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_u32)(uint64_t x)
 {
     if (x > 0xffffffffu) {
         SET_QC();
@@ -1378,7 +1374,7 @@ uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
     return x;
 }
 
-uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
+uint32_t HELPER(neon_narrow_sat_s32)(uint64_t x)
 {
     if ((int64_t)x != (int32_t)x) {
         SET_QC();
@@ -1485,7 +1481,7 @@ uint64_t HELPER(neon_subl_u32)(uint64_t a, uint64_t b)
     return (a - b) ^ mask;
 }
 
-uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s32)(uint64_t a, uint64_t b)
 {
     uint32_t x, y;
     uint32_t low, high;
@@ -1507,7 +1503,7 @@ uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
     return low | ((uint64_t)high << 32);
 }
 
-uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(neon_addl_saturate_s64)(uint64_t a, uint64_t b)
 {
     uint64_t result;
 
@@ -1679,7 +1675,7 @@ uint64_t HELPER(neon_negl_u64)(uint64_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s8)(uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1699,7 +1695,7 @@ uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s8)(uint32_t x)
 {
     neon_s8 vec;
     NEON_UNPACK(neon_s8, vec, x);
@@ -1719,7 +1715,7 @@ uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
     } else if (x < 0) { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s16)(uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1737,7 +1733,7 @@ uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
     } else { \
         x = -x; \
     }} while (0)
-uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s16)(uint32_t x)
 {
     neon_s16 vec;
     NEON_UNPACK(neon_s16, vec, x);
@@ -1748,7 +1744,7 @@ uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
 }
 #undef DO_QNEG16
 
-uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qabs_s32)(uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1759,7 +1755,7 @@ uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
     return x;
 }
 
-uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
+uint32_t HELPER(neon_qneg_s32)(uint32_t x)
 {
     if (x == SIGNBIT) {
         SET_QC();
@@ -1842,7 +1838,7 @@ uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
 
-void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip8)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1870,7 +1866,7 @@ void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip16)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1890,7 +1886,7 @@ void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qunzip32)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1906,7 +1902,7 @@ void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip8)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1922,7 +1918,7 @@ void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_unzip16)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -1934,7 +1930,7 @@ void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip8)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1962,7 +1958,7 @@ void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip16)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1982,7 +1978,7 @@ void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_qzip32)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm0 = float64_val(env->vfp.regs[rm]);
     uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
@@ -1998,7 +1994,7 @@ void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd + 1] = make_float64(d1);
 }
 
-void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip8)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
@@ -2014,7 +2010,7 @@ void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rd] = make_float64(d0);
 }
 
-void HELPER(neon_zip16)(CPUState *env, uint32_t rd, uint32_t rm)
+void HELPER(neon_zip16)(uint32_t rd, uint32_t rm)
 {
     uint64_t zm = float64_val(env->vfp.regs[rm]);
     uint64_t zd = float64_val(env->vfp.regs[rd]);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 33417e6..53c40ac 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3656,13 +3656,13 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip8(tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip16(tmp, tmp2);
             break;
         case 2:
-            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
+            gen_helper_neon_qunzip32(tmp, tmp2);
             break;
         default:
             abort();
@@ -3670,10 +3670,10 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_unzip8(tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_unzip16(tmp, tmp2);
             break;
         default:
             abort();
@@ -3695,13 +3695,13 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
     if (q) {
         switch (size) {
         case 0:
-            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip8(tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip16(tmp, tmp2);
             break;
         case 2:
-            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
+            gen_helper_neon_qzip32(tmp, tmp2);
             break;
         default:
             abort();
@@ -3709,10 +3709,10 @@ static int gen_neon_zip(int rd, int rm, int size, int q)
     } else {
         switch (size) {
         case 0:
-            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
+            gen_helper_neon_zip8(tmp, tmp2);
             break;
         case 1:
-            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
+            gen_helper_neon_zip16(tmp, tmp2);
             break;
         default:
             abort();
@@ -4063,9 +4063,9 @@ static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
-    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
-    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
+    case 0: gen_helper_neon_narrow_sat_s8(dest, src); break;
+    case 1: gen_helper_neon_narrow_sat_s16(dest, src); break;
+    case 2: gen_helper_neon_narrow_sat_s32(dest, src); break;
     default: abort();
     }
 }
@@ -4073,9 +4073,9 @@ static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
-    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
-    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
+    case 0: gen_helper_neon_narrow_sat_u8(dest, src); break;
+    case 1: gen_helper_neon_narrow_sat_u16(dest, src); break;
+    case 2: gen_helper_neon_narrow_sat_u32(dest, src); break;
     default: abort();
     }
 }
@@ -4083,9 +4083,9 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
 {
     switch (size) {
-    case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
-    case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
-    case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
+    case 0: gen_helper_neon_unarrow_sat8(dest, src); break;
+    case 1: gen_helper_neon_unarrow_sat16(dest, src); break;
+    case 2: gen_helper_neon_unarrow_sat32(dest, src); break;
     default: abort();
     }
 }
@@ -4177,8 +4177,8 @@ static inline void gen_neon_negl(TCGv_i64 var, int size)
 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
 {
     switch (size) {
-    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
-    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
+    case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break;
+    case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break;
     default: abort();
     }
 }
@@ -4271,20 +4271,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 switch (op) {
                 case 1: /* VQADD */
                     if (u) {
-                        gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
-                                                 cpu_V0, cpu_V1);
+                        gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
-                                                 cpu_V0, cpu_V1);
+                        gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
                     }
                     break;
                 case 5: /* VQSUB */
                     if (u) {
-                        gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
-                                                 cpu_V0, cpu_V1);
+                        gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
-                                                 cpu_V0, cpu_V1);
+                        gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
                     }
                     break;
                 case 8: /* VSHL */
@@ -4296,11 +4292,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case 9: /* VQSHL */
                     if (u) {
-                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
-                                                 cpu_V1, cpu_V0);
+                        gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
-                        gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
-                                                 cpu_V1, cpu_V0);
+                        gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
                 case 10: /* VRSHL */
@@ -4312,11 +4306,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     break;
                 case 11: /* VQRSHL */
                     if (u) {
-                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
-                                                  cpu_V1, cpu_V0);
+                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
                     } else {
-                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
-                                                  cpu_V1, cpu_V0);
+                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
                     }
                     break;
                 case 16:
@@ -4388,7 +4380,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(hadd);
             break;
         case 1: /* VQADD */
-            GEN_NEON_INTEGER_OP_ENV(qadd);
+            GEN_NEON_INTEGER_OP(qadd);
             break;
         case 2: /* VRHADD */
             GEN_NEON_INTEGER_OP(rhadd);
@@ -4431,7 +4423,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(hsub);
             break;
         case 5: /* VQSUB */
-            GEN_NEON_INTEGER_OP_ENV(qsub);
+            GEN_NEON_INTEGER_OP(qsub);
             break;
         case 6: /* VCGT */
             GEN_NEON_INTEGER_OP(cgt);
@@ -4443,13 +4435,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             GEN_NEON_INTEGER_OP(shl);
             break;
         case 9: /* VQSHL */
-            GEN_NEON_INTEGER_OP_ENV(qshl);
+            GEN_NEON_INTEGER_OP(qshl);
             break;
         case 10: /* VRSHL */
             GEN_NEON_INTEGER_OP(rshl);
             break;
         case 11: /* VQRSHL */
-            GEN_NEON_INTEGER_OP_ENV(qrshl);
+            GEN_NEON_INTEGER_OP(qrshl);
             break;
         case 12: /* VMAX */
             GEN_NEON_INTEGER_OP(max);
@@ -4532,14 +4524,14 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
         case 22: /* Hultiply high.  */
             if (!u) { /* VQDMULH */
                 switch (size) {
-                case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
-                case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
+                case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
+                case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
                 default: return 1;
                 }
             } else { /* VQRDHMUL */
                 switch (size) {
-                case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
-                case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
+                case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
+                case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
                 default: return 1;
                 }
             }
@@ -4710,7 +4702,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         case 6: /* VQSHLU */
                             if (u) {
-                                gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
+                                gen_helper_neon_qshlu_s64(cpu_V0,
                                                           cpu_V0, cpu_V1);
                             } else {
                                 return 1;
@@ -4718,10 +4710,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         case 7: /* VQSHL */
                             if (u) {
-                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
+                                gen_helper_neon_qshl_u64(cpu_V0,
                                                          cpu_V0, cpu_V1);
                             } else {
-                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
+                                gen_helper_neon_qshl_s64(cpu_V0,
                                                          cpu_V0, cpu_V1);
                             }
                             break;
@@ -4780,23 +4772,20 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             }
                             switch (size) {
                             case 0:
-                                gen_helper_neon_qshlu_s8(tmp, cpu_env,
-                                                         tmp, tmp2);
+                                gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
                                 break;
                             case 1:
-                                gen_helper_neon_qshlu_s16(tmp, cpu_env,
-                                                          tmp, tmp2);
+                                gen_helper_neon_qshlu_s16(tmp, tmp, tmp2);
                                 break;
                             case 2:
-                                gen_helper_neon_qshlu_s32(tmp, cpu_env,
-                                                          tmp, tmp2);
+                                gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
                                 break;
                             default:
                                 return 1;
                             }
                             break;
                         case 7: /* VQSHL */
-                            GEN_NEON_INTEGER_OP_ENV(qshl);
+                            GEN_NEON_INTEGER_OP(qshl);
                             break;
                         }
                         tcg_temp_free_i32(tmp2);
@@ -5259,15 +5248,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tmp2 = neon_load_reg(rn, pass);
                         if (op == 12) {
                             if (size == 1) {
-                                gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                                gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2);
                             } else {
-                                gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                                gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2);
                             }
                         } else if (op == 13) {
                             if (size == 1) {
-                                gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                                gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2);
                             } else {
-                                gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                                gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
                             }
                         } else if (op & 1) {
                             gen_helper_neon_mul_f32(tmp, tmp, tmp2);
@@ -5614,17 +5603,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         case 14: /* VQABS */
                             switch (size) {
-                            case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
-                            case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
-                            case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
+                            case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
+                            case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
+                            case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
                             default: return 1;
                             }
                             break;
                         case 15: /* VQNEG */
                             switch (size) {
-                            case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
-                            case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
-                            case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
+                            case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
+                            case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
+                            case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
                             default: return 1;
                             }
                             break;
commit 348883d4828d7434e1053407818598f7fb15e594
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Apr 4 11:46:32 2011 +0100

    Makefile.target: Allow target helpers to be in any *_helper.c file
    
    Build all files matching *_helper.c with HELPER_CFLAGS, not just
    op_helper.c. This allows you to put target helper functions which
    use the global 'env' variable in multiple source files.
    
    This only affects the ARM target as all the other targets currently only
    have op_helper.c.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile.target b/Makefile.target
index 2f76714..d5761b7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -94,7 +94,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o cpu-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+%_helper.o cpu-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in cpu-exec.c.
commit c53c1258a455cbe9afd7e5c572578646df30d438
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Apr 4 14:48:08 2011 +1000

    Fix non-portable format string in usb-ccid.c
    
    At one point, usb-ccid.c attempts to use a %lX format specifier to print
    a uint64_t, which is only correct on some host platforms.  This patch
    corrects the statement to use the stdint specified PRIX64 constant instead.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 723b2e3..44156cc 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -1199,7 +1199,7 @@ void ccid_card_card_error(CCIDCardState *card, uint64_t error)
 
     s->bmCommandStatus = COMMAND_STATUS_FAILED;
     s->last_answer_error = error;
-    DPRINTF(s, 1, "VSC_Error: %lX\n", s->last_answer_error);
+    DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
     /* TODO: these error's should be more verbose and propogated to the guest.*/
     /*
      * We flush all pending answers on CardRemove message in ccid-card-passthru,
commit d118aa6b4a8fecb1c5a4747fd0f88a015883bf85
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:45 2011 +0100

    MAINTAINERS: add Milkymist board
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 9f3ff0e..e6f853d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -214,6 +214,11 @@ M: Michael Walle <michael at walle.cc>
 S: Maintained
 F: hw/lm32_boards.c
 
+milkymist
+M: Michael Walle <michael at walle.cc>
+S: Maintained
+F: hw/milkymist.c
+
 M68K Machines
 -------------
 an5206
commit 5052d2277fdcc08afda245ebfce3163935dc7dfb
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:44 2011 +0100

    lm32: add support for the Milkymist board
    
    This patch adds almost complete support for the Milkymist system-on-chip
    (http://www.milkymist.org).
    
    Additional to running bare metal applications, booting a linux kernel with
    initrd is supported.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 2a65e15..2f76714 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -260,6 +260,7 @@ obj-ppc-y += xilinx_ethlite.o
 
 # LM32 boards
 obj-lm32-y += lm32_boards.o
+obj-lm32-y += milkymist.o
 
 # LM32 peripherals
 obj-lm32-y += lm32_pic.o
diff --git a/default-configs/lm32-softmmu.mak b/default-configs/lm32-softmmu.mak
index 3e7f57e..0d19974 100644
--- a/default-configs/lm32-softmmu.mak
+++ b/default-configs/lm32-softmmu.mak
@@ -1,5 +1,6 @@
 # Default configuration for lm32-softmmu
 
 CONFIG_PTIMER=y
+CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_SD=y
diff --git a/hw/milkymist.c b/hw/milkymist.c
new file mode 100644
index 0000000..8defad8
--- /dev/null
+++ b/hw/milkymist.c
@@ -0,0 +1,216 @@
+/*
+ *  QEMU model for the Milkymist board.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+#include "net.h"
+#include "flash.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+#include "blockdev.h"
+#include "milkymist-hw.h"
+#include "lm32.h"
+
+#define BIOS_FILENAME    "mmone-bios.bin"
+#define BIOS_OFFSET      0x00860000
+#define BIOS_SIZE        (512*1024)
+#define KERNEL_LOAD_ADDR 0x40000000
+
+typedef struct {
+    CPUState *env;
+    target_phys_addr_t bootstrap_pc;
+    target_phys_addr_t flash_base;
+    target_phys_addr_t initrd_base;
+    size_t initrd_size;
+    target_phys_addr_t cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPUState *env = opaque;
+
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetInfo *reset_info = opaque;
+    CPUState *env = reset_info->env;
+
+    cpu_reset(env);
+
+    /* init defaults */
+    env->pc = reset_info->bootstrap_pc;
+    env->regs[R_R1] = reset_info->cmdline_base;
+    env->regs[R_R2] = reset_info->initrd_base;
+    env->regs[R_R3] = reset_info->initrd_base + reset_info->initrd_size;
+    env->eba = reset_info->flash_base;
+    env->deba = reset_info->flash_base;
+}
+
+static void
+milkymist_init(ram_addr_t ram_size_not_used,
+                          const char *boot_device,
+                          const char *kernel_filename,
+                          const char *kernel_cmdline,
+                          const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env;
+    int kernel_size;
+    DriveInfo *dinfo;
+    ram_addr_t phys_sdram;
+    ram_addr_t phys_flash;
+    qemu_irq irq[32], *cpu_irq;
+    int i;
+    char *bios_filename;
+    ResetInfo *reset_info;
+
+    /* memory map */
+    target_phys_addr_t flash_base   = 0x00000000;
+    size_t flash_sector_size        = 128 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    target_phys_addr_t sdram_base   = 0x40000000;
+    size_t sdram_size               = 128 * 1024 * 1024;
+
+    target_phys_addr_t initrd_base  = sdram_base + 0x1002000;
+    target_phys_addr_t cmdline_base = sdram_base + 0x1000000;
+    size_t initrd_max = sdram_size - 0x1002000;
+
+    reset_info = qemu_mallocz(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    env = cpu_init(cpu_model);
+    reset_info->env = env;
+
+    cpu_lm32_set_phys_msb_ignore(env, 1);
+
+    phys_sdram = qemu_ram_alloc(NULL, "milkymist.sdram", sdram_size);
+    cpu_register_physical_memory(sdram_base, sdram_size,
+            phys_sdram | IO_MEM_RAM);
+
+    phys_flash = qemu_ram_alloc(NULL, "milkymist.flash", flash_size);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Numonyx JS28F256J3F105 */
+    pflash_cfi01_register(flash_base, phys_flash,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 2,
+                          0x00, 0x89, 0x00, 0x1d, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    /* load bios rom */
+    if (bios_name == NULL) {
+        bios_name = BIOS_FILENAME;
+    }
+    bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    if (bios_filename) {
+        load_image_targphys(bios_filename, BIOS_OFFSET, BIOS_SIZE);
+    }
+
+    reset_info->bootstrap_pc = BIOS_OFFSET;
+
+    /* if no kernel is given no valid bios rom is a fatal error */
+    if (!kernel_filename && !dinfo && !bios_filename) {
+        fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n",
+                bios_name);
+        exit(1);
+    }
+
+    milkymist_uart_create(0x60000000, irq[0], irq[1]);
+    milkymist_sysctl_create(0x60001000, irq[2], irq[3], irq[4],
+            80000000, 0x10014d31, 0x0000041f, 0x00000001);
+    milkymist_hpdmc_create(0x60002000);
+    milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
+    milkymist_memcard_create(0x60004000);
+    milkymist_ac97_create(0x60005000, irq[5], irq[6], irq[7], irq[8]);
+    milkymist_pfpu_create(0x60006000, irq[9]);
+    milkymist_tmu2_create(0x60007000, irq[10]);
+    milkymist_minimac_create(0x60008000, irq[11], irq[12]);
+    milkymist_softusb_create(0x6000f000, irq[17],
+            0x20000000, 0x1000, 0x20020000, 0x2000);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    if (kernel_filename) {
+        uint64_t entry;
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, sdram_base,
+                                              sdram_size);
+            reset_info->bootstrap_pc = sdram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    if (kernel_cmdline && strlen(kernel_cmdline)) {
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
+                kernel_cmdline);
+        reset_info->cmdline_base = (uint32_t)cmdline_base;
+    }
+
+    if (initrd_filename) {
+        size_t initrd_size;
+        initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                initrd_max);
+        reset_info->initrd_base = (uint32_t)initrd_base;
+        reset_info->initrd_size = (uint32_t)initrd_size;
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static QEMUMachine milkymist_machine = {
+    .name = "milkymist",
+    .desc = "Milkymist One",
+    .init = milkymist_init,
+    .is_default = 0
+};
+
+static void milkymist_machine_init(void)
+{
+    qemu_register_machine(&milkymist_machine);
+}
+
+machine_init(milkymist_machine_init);
commit 38d3339398ec0cffa53834ed32306836a4ad2c78
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:43 2011 +0100

    lm32: add milkymist hw support functions
    
    This patch adds wrappers for easy creation of the qdev devices.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
new file mode 100644
index 0000000..15acdbc
--- /dev/null
+++ b/hw/milkymist-hw.h
@@ -0,0 +1,204 @@
+#ifndef QEMU_HW_MILKYMIST_H
+#define QEMU_HW_MILKYMIST_H
+
+static inline DeviceState *milkymist_uart_create(target_phys_addr_t base,
+        qemu_irq rx_irq, qemu_irq tx_irq)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-uart");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_hpdmc_create(target_phys_addr_t base)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-hpdmc");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_memcard_create(target_phys_addr_t base)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-memcard");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_vgafb_create(target_phys_addr_t base,
+        uint32_t fb_offset, uint32_t fb_mask)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-vgafb");
+    qdev_prop_set_uint32(dev, "fb_offset", fb_offset);
+    qdev_prop_set_uint32(dev, "fb_mask", fb_mask);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_sysctl_create(target_phys_addr_t base,
+        qemu_irq gpio_irq, qemu_irq timer0_irq, qemu_irq timer1_irq,
+        uint32_t freq_hz, uint32_t system_id, uint32_t capabilities,
+        uint32_t gpio_strappings)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-sysctl");
+    qdev_prop_set_uint32(dev, "frequency", freq_hz);
+    qdev_prop_set_uint32(dev, "systemid", system_id);
+    qdev_prop_set_uint32(dev, "capabilities", capabilities);
+    qdev_prop_set_uint32(dev, "gpio_strappings", gpio_strappings);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, gpio_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, timer0_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2, timer1_irq);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_pfpu_create(target_phys_addr_t base,
+        qemu_irq irq)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-pfpu");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
+
+#ifdef CONFIG_OPENGL
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+static const int glx_fbconfig_attr[] = {
+    GLX_GREEN_SIZE, 5,
+    GLX_GREEN_SIZE, 6,
+    GLX_BLUE_SIZE, 5,
+    None
+};
+#endif
+
+static inline DeviceState *milkymist_tmu2_create(target_phys_addr_t base,
+        qemu_irq irq)
+{
+#ifdef CONFIG_OPENGL
+    DeviceState *dev;
+    Display *d;
+    GLXFBConfig *configs;
+    int nelements;
+    int ver_major, ver_minor;
+
+    if (display_type == DT_NOGRAPHIC) {
+        return NULL;
+    }
+
+    /* check that GLX will work */
+    d = XOpenDisplay(NULL);
+    if (d == NULL) {
+        return NULL;
+    }
+
+    if (!glXQueryVersion(d, &ver_major, &ver_minor)) {
+        /* Yeah, sometimes getting the GLX version can fail.
+         * Isn't X beautiful? */
+        XCloseDisplay(d);
+        return NULL;
+    }
+
+    if ((ver_major < 1) || ((ver_major == 1) && (ver_minor < 3))) {
+        printf("Your GLX version is %d.%d,"
+          "but TMU emulation needs at least 1.3. TMU disabled.\n",
+          ver_major, ver_minor);
+        XCloseDisplay(d);
+        return NULL;
+    }
+
+    configs = glXChooseFBConfig(d, 0, glx_fbconfig_attr, &nelements);
+    if (configs == NULL) {
+        XCloseDisplay(d);
+        return NULL;
+    }
+
+    XFree(configs);
+    XCloseDisplay(d);
+
+    dev = qdev_create(NULL, "milkymist-tmu2");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
+#else
+    return NULL;
+#endif
+}
+
+static inline DeviceState *milkymist_ac97_create(target_phys_addr_t base,
+        qemu_irq crrequest_irq, qemu_irq crreply_irq, qemu_irq dmar_irq,
+        qemu_irq dmaw_irq)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-ac97");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, crrequest_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, crreply_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2, dmar_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 3, dmaw_irq);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_minimac_create(target_phys_addr_t base,
+        qemu_irq rx_irq, qemu_irq tx_irq)
+{
+    DeviceState *dev;
+
+    qemu_check_nic_model(&nd_table[0], "minimac");
+    dev = qdev_create(NULL, "milkymist-minimac");
+    qdev_set_nic_properties(dev, &nd_table[0]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+
+    return dev;
+}
+
+static inline DeviceState *milkymist_softusb_create(target_phys_addr_t base,
+        qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size,
+        uint32_t dmem_base, uint32_t dmem_size)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "milkymist-softusb");
+    qdev_prop_set_uint32(dev, "pmem_base", pmem_base);
+    qdev_prop_set_uint32(dev, "pmem_size", pmem_size);
+    qdev_prop_set_uint32(dev, "dmem_base", dmem_base);
+    qdev_prop_set_uint32(dev, "dmem_size", dmem_size);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
+}
+
+#endif /* QEMU_HW_MILKYMIST_H */
commit d23948b15a9920fb7f6374b55a6db1ecff81f3ee
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:42 2011 +0100

    lm32: add Milkymist VGAFB support
    
    This patch adds support for Milkymist's VGA framebuffer.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index c009117..2a65e15 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -276,6 +276,8 @@ obj-lm32-y += milkymist-softusb.o
 obj-lm32-y += milkymist-sysctl.o
 obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
 obj-lm32-y += milkymist-uart.o
+obj-lm32-y += milkymist-vgafb.o
+obj-lm32-y += framebuffer.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
new file mode 100644
index 0000000..8922731
--- /dev/null
+++ b/hw/milkymist-vgafb.c
@@ -0,0 +1,318 @@
+
+/*
+ *  QEMU model of the Milkymist VGA framebuffer.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/vgafb.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "console.h"
+#include "framebuffer.h"
+#include "pixel_ops.h"
+#include "qemu-error.h"
+
+#define BITS 8
+#include "milkymist-vgafb_template.h"
+#define BITS 15
+#include "milkymist-vgafb_template.h"
+#define BITS 16
+#include "milkymist-vgafb_template.h"
+#define BITS 24
+#include "milkymist-vgafb_template.h"
+#define BITS 32
+#include "milkymist-vgafb_template.h"
+
+enum {
+    R_CTRL = 0,
+    R_HRES,
+    R_HSYNC_START,
+    R_HSYNC_END,
+    R_HSCAN,
+    R_VRES,
+    R_VSYNC_START,
+    R_VSYNC_END,
+    R_VSCAN,
+    R_BASEADDRESS,
+    R_BASEADDRESS_ACT,
+    R_BURST_COUNT,
+    R_SOURCE_CLOCK,
+    R_MAX
+};
+
+enum {
+    CTRL_RESET = (1<<0),
+};
+
+struct MilkymistVgafbState {
+    SysBusDevice busdev;
+    DisplayState *ds;
+
+    int invalidate;
+    uint32_t fb_offset;
+    uint32_t fb_mask;
+
+    uint32_t regs[R_MAX];
+};
+typedef struct MilkymistVgafbState MilkymistVgafbState;
+
+static int vgafb_enabled(MilkymistVgafbState *s)
+{
+    return !(s->regs[R_CTRL] & CTRL_RESET);
+}
+
+static void vgafb_update_display(void *opaque)
+{
+    MilkymistVgafbState *s = opaque;
+    int first = 0;
+    int last = 0;
+    drawfn fn;
+
+    if (!vgafb_enabled(s)) {
+        return;
+    }
+
+    int dest_width = s->regs[R_HRES];
+
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 0:
+        return;
+    case 8:
+        fn = draw_line_8;
+        break;
+    case 15:
+        fn = draw_line_15;
+        dest_width *= 2;
+        break;
+    case 16:
+        fn = draw_line_16;
+        dest_width *= 2;
+        break;
+    case 24:
+        fn = draw_line_24;
+        dest_width *= 3;
+        break;
+    case 32:
+        fn = draw_line_32;
+        dest_width *= 4;
+        break;
+    default:
+        hw_error("milkymist_vgafb: bad color depth\n");
+        break;
+    }
+
+    framebuffer_update_display(s->ds,
+                               s->regs[R_BASEADDRESS] + s->fb_offset,
+                               s->regs[R_HRES],
+                               s->regs[R_VRES],
+                               s->regs[R_HRES] * 2,
+                               dest_width,
+                               0,
+                               s->invalidate,
+                               fn,
+                               NULL,
+                               &first, &last);
+
+    if (first >= 0) {
+        dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
+    }
+    s->invalidate = 0;
+}
+
+static void vgafb_invalidate_display(void *opaque)
+{
+    MilkymistVgafbState *s = opaque;
+    s->invalidate = 1;
+}
+
+static void vgafb_resize(MilkymistVgafbState *s)
+{
+    if (!vgafb_enabled(s)) {
+        return;
+    }
+
+    qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
+    s->invalidate = 1;
+}
+
+static uint32_t vgafb_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistVgafbState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTRL:
+    case R_HRES:
+    case R_HSYNC_START:
+    case R_HSYNC_END:
+    case R_HSCAN:
+    case R_VRES:
+    case R_VSYNC_START:
+    case R_VSYNC_END:
+    case R_VSCAN:
+    case R_BASEADDRESS:
+    case R_BURST_COUNT:
+    case R_SOURCE_CLOCK:
+        r = s->regs[addr];
+    break;
+    case R_BASEADDRESS_ACT:
+        r = s->regs[R_BASEADDRESS];
+    break;
+
+    default:
+        error_report("milkymist_vgafb: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_vgafb_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void
+vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistVgafbState *s = opaque;
+
+    trace_milkymist_vgafb_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTRL:
+    case R_HSYNC_START:
+    case R_HSYNC_END:
+    case R_HSCAN:
+    case R_VSYNC_START:
+    case R_VSYNC_END:
+    case R_VSCAN:
+    case R_BURST_COUNT:
+    case R_SOURCE_CLOCK:
+        s->regs[addr] = value;
+        break;
+    case R_BASEADDRESS:
+        if (value & 0x1f) {
+            error_report("milkymist_vgafb: framebuffer base address have to "
+                     "be 32 byte aligned");
+            break;
+        }
+        s->regs[addr] = value & s->fb_mask;
+        s->invalidate = 1;
+        break;
+    case R_HRES:
+    case R_VRES:
+        s->regs[addr] = value;
+        vgafb_resize(s);
+        break;
+    case R_BASEADDRESS_ACT:
+        error_report("milkymist_vgafb: write to read-only register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+
+    default:
+        error_report("milkymist_vgafb: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const vgafb_read_fn[] = {
+   NULL,
+   NULL,
+   &vgafb_read
+};
+
+static CPUWriteMemoryFunc * const vgafb_write_fn[] = {
+   NULL,
+   NULL,
+   &vgafb_write
+};
+
+static void milkymist_vgafb_reset(DeviceState *d)
+{
+    MilkymistVgafbState *s = container_of(d, MilkymistVgafbState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    /* defaults */
+    s->regs[R_CTRL] = CTRL_RESET;
+    s->regs[R_HRES] = 640;
+    s->regs[R_VRES] = 480;
+    s->regs[R_BASEADDRESS] = 0;
+}
+
+static int milkymist_vgafb_init(SysBusDevice *dev)
+{
+    MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
+    int vgafb_regs;
+
+    vgafb_regs = cpu_register_io_memory(vgafb_read_fn, vgafb_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, vgafb_regs);
+
+    s->ds = graphic_console_init(vgafb_update_display,
+                                 vgafb_invalidate_display,
+                                 NULL, NULL, s);
+
+    return 0;
+}
+
+static int vgafb_post_load(void *opaque, int version_id)
+{
+    vgafb_invalidate_display(opaque);
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_vgafb = {
+    .name = "milkymist-vgafb",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = vgafb_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_vgafb_info = {
+    .init = milkymist_vgafb_init,
+    .qdev.name  = "milkymist-vgafb",
+    .qdev.size  = sizeof(MilkymistVgafbState),
+    .qdev.vmsd  = &vmstate_milkymist_vgafb,
+    .qdev.reset = milkymist_vgafb_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
+        DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void milkymist_vgafb_register(void)
+{
+    sysbus_register_withprop(&milkymist_vgafb_info);
+}
+
+device_init(milkymist_vgafb_register)
diff --git a/hw/milkymist-vgafb_template.h b/hw/milkymist-vgafb_template.h
new file mode 100644
index 0000000..69af9ef
--- /dev/null
+++ b/hw/milkymist-vgafb_template.h
@@ -0,0 +1,74 @@
+/*
+ *  QEMU model of the Milkymist VGA framebuffer.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if BITS == 8
+#define COPY_PIXEL(to, r, g, b)                    \
+    do {                                           \
+        *to = rgb_to_pixel8(r, g, b);              \
+        to += 1;                                   \
+    } while (0)
+#elif BITS == 15
+#define COPY_PIXEL(to, r, g, b)                    \
+    do {                                           \
+        *(uint16_t *)to = rgb_to_pixel15(r, g, b); \
+        to += 2;                                   \
+    } while (0)
+#elif BITS == 16
+#define COPY_PIXEL(to, r, g, b)                    \
+    do {                                           \
+        *(uint16_t *)to = rgb_to_pixel16(r, g, b); \
+        to += 2;                                   \
+    } while (0)
+#elif BITS == 24
+#define COPY_PIXEL(to, r, g, b)                    \
+    do {                                           \
+        uint32 tmp = rgb_to_pixel24(r, g, b);      \
+        *(to++) =         tmp & 0xff;              \
+        *(to++) =  (tmp >> 8) & 0xff;              \
+        *(to++) = (tmp >> 16) & 0xff;              \
+    } while (0)
+#elif BITS == 32
+#define COPY_PIXEL(to, r, g, b)                    \
+    do {                                           \
+        *(uint32_t *)to = rgb_to_pixel32(r, g, b); \
+        to += 4;                                   \
+    } while (0)
+#else
+#error unknown bit depth
+#endif
+
+static void glue(draw_line_, BITS)(void *opaque, uint8_t *d, const uint8_t *s,
+        int width, int deststep)
+{
+    uint16_t rgb565;
+    uint8_t r, g, b;
+
+    while (width--) {
+        rgb565 = lduw_raw(s);
+        r = ((rgb565 >> 11) & 0x1f) << 3;
+        g = ((rgb565 >>  5) & 0x3f) << 2;
+        b = ((rgb565 >>  0) & 0x1f) << 3;
+        COPY_PIXEL(d, r, g, b);
+        s += 2;
+    }
+}
+
+#undef BITS
+#undef COPY_PIXEL
diff --git a/trace-events b/trace-events
index 55f3de5..06efdb7 100644
--- a/trace-events
+++ b/trace-events
@@ -355,3 +355,7 @@ disable milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x val
 disable milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
 disable milkymist_uart_pulse_irq_rx(void) "Pulse IRQ RX"
 disable milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX"
+
+# hw/milkymist-vgafb.c
+disable milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
commit 883de16b464554e195fe7e20daaa9525cfeaf3a2
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:41 2011 +0100

    lm32: add Milkymist UART support
    
    This patch adds support for Milkymist's simple UART.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 6581519..c009117 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -275,6 +275,7 @@ obj-lm32-y += milkymist-pfpu.o
 obj-lm32-y += milkymist-softusb.o
 obj-lm32-y += milkymist-sysctl.o
 obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
+obj-lm32-y += milkymist-uart.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
new file mode 100644
index 0000000..56c90da
--- /dev/null
+++ b/hw/milkymist-uart.c
@@ -0,0 +1,180 @@
+/*
+ *  QEMU model of the Milkymist UART block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/uart.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-char.h"
+#include "qemu-error.h"
+
+enum {
+    R_RXTX = 0,
+    R_DIV,
+    R_MAX
+};
+
+struct MilkymistUartState {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+    qemu_irq rx_irq;
+    qemu_irq tx_irq;
+
+    uint32_t regs[R_MAX];
+};
+typedef struct MilkymistUartState MilkymistUartState;
+
+static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistUartState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_RXTX:
+    case R_DIV:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_uart: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_uart_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistUartState *s = opaque;
+    unsigned char ch = value;
+
+    trace_milkymist_uart_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_RXTX:
+        if (s->chr) {
+            qemu_chr_write(s->chr, &ch, 1);
+        }
+        trace_milkymist_uart_pulse_irq_tx();
+        qemu_irq_pulse(s->tx_irq);
+        break;
+    case R_DIV:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_uart: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const uart_read_fn[] = {
+    NULL,
+    NULL,
+    &uart_read,
+};
+
+static CPUWriteMemoryFunc * const uart_write_fn[] = {
+    NULL,
+    NULL,
+    &uart_write,
+};
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+    MilkymistUartState *s = opaque;
+
+    s->regs[R_RXTX] = *buf;
+    trace_milkymist_uart_pulse_irq_rx();
+    qemu_irq_pulse(s->rx_irq);
+}
+
+static int uart_can_rx(void *opaque)
+{
+    return 1;
+}
+
+static void uart_event(void *opaque, int event)
+{
+}
+
+static void milkymist_uart_reset(DeviceState *d)
+{
+    MilkymistUartState *s = container_of(d, MilkymistUartState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+}
+
+static int milkymist_uart_init(SysBusDevice *dev)
+{
+    MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
+    int uart_regs;
+
+    sysbus_init_irq(dev, &s->rx_irq);
+    sysbus_init_irq(dev, &s->tx_irq);
+
+    uart_regs = cpu_register_io_memory(uart_read_fn, uart_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+
+    s->chr = qdev_init_chardev(&dev->qdev);
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_uart = {
+    .name = "milkymist-uart",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistUartState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_uart_info = {
+    .init = milkymist_uart_init,
+    .qdev.name  = "milkymist-uart",
+    .qdev.size  = sizeof(MilkymistUartState),
+    .qdev.vmsd  = &vmstate_milkymist_uart,
+    .qdev.reset = milkymist_uart_reset,
+};
+
+static void milkymist_uart_register(void)
+{
+    sysbus_register_withprop(&milkymist_uart_info);
+}
+
+device_init(milkymist_uart_register)
diff --git a/trace-events b/trace-events
index 3a88adf..55f3de5 100644
--- a/trace-events
+++ b/trace-events
@@ -349,3 +349,9 @@ disable milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x val
 disable milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
 disable milkymist_tmu2_start(void) "Start TMU"
 disable milkymist_tmu2_pulse_irq(void) "Pulse IRQ"
+
+# hw/milkymist-uart.c
+disable milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_uart_pulse_irq_rx(void) "Pulse IRQ RX"
+disable milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX"
commit 0670dadd64be8c06d176e797bfc1943ecbce6eb2
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:40 2011 +0100

    lm32: add Milkymist TMU2 support
    
    This patch adds support for Milkymist's texture mapping unit. For fast
    computation this model needs hardware accelerated 3D graphics support
    (OpenGL). There is no graphical output, all computations belong to internal
    framebuffers only.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index c117565..6581519 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -274,6 +274,7 @@ obj-lm32-y += milkymist-minimac.o
 obj-lm32-y += milkymist-pfpu.o
 obj-lm32-y += milkymist-softusb.o
 obj-lm32-y += milkymist-sysctl.o
+obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
new file mode 100644
index 0000000..9cebe31
--- /dev/null
+++ b/hw/milkymist-tmu2.c
@@ -0,0 +1,481 @@
+/*
+ *  QEMU model of the Milkymist texture mapping unit.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *  Copyright (c) 2010 Sebastien Bourdeauducq
+ *                       <sebastien.bourdeauducq at lekernel.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/tmu2.pdf
+ *
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-error.h"
+
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+enum {
+    R_CTL = 0,
+    R_HMESHLAST,
+    R_VMESHLAST,
+    R_BRIGHTNESS,
+    R_CHROMAKEY,
+    R_VERTICESADDR,
+    R_TEXFBUF,
+    R_TEXHRES,
+    R_TEXVRES,
+    R_TEXHMASK,
+    R_TEXVMASK,
+    R_DSTFBUF,
+    R_DSTHRES,
+    R_DSTVRES,
+    R_DSTHOFFSET,
+    R_DSTVOFFSET,
+    R_DSTSQUAREW,
+    R_DSTSQUAREH,
+    R_ALPHA,
+    R_MAX
+};
+
+enum {
+    CTL_START_BUSY  = (1<<0),
+    CTL_CHROMAKEY   = (1<<1),
+};
+
+enum {
+    MAX_BRIGHTNESS = 63,
+    MAX_ALPHA      = 63,
+};
+
+enum {
+    MESH_MAXSIZE = 128,
+};
+
+struct vertex {
+    int x;
+    int y;
+} __attribute__((packed));
+
+struct MilkymistTMU2State {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint32_t regs[R_MAX];
+
+    Display *dpy;
+    GLXFBConfig glx_fb_config;
+    GLXContext glx_context;
+};
+typedef struct MilkymistTMU2State MilkymistTMU2State;
+
+static const int glx_fbconfig_attr[] = {
+    GLX_GREEN_SIZE, 5,
+    GLX_GREEN_SIZE, 6,
+    GLX_BLUE_SIZE, 5,
+    None
+};
+
+static int tmu2_glx_init(MilkymistTMU2State *s)
+{
+    GLXFBConfig *configs;
+    int nelements;
+
+    s->dpy = XOpenDisplay(NULL); /* FIXME: call XCloseDisplay() */
+    if (s->dpy == NULL) {
+        return 1;
+    }
+
+    configs = glXChooseFBConfig(s->dpy, 0, glx_fbconfig_attr, &nelements);
+    if (configs == NULL) {
+        return 1;
+    }
+
+    s->glx_fb_config = *configs;
+    XFree(configs);
+
+    /* FIXME: call glXDestroyContext() */
+    s->glx_context = glXCreateNewContext(s->dpy, s->glx_fb_config,
+            GLX_RGBA_TYPE, NULL, 1);
+    if (s->glx_context == NULL) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void tmu2_gl_map(struct vertex *mesh, int texhres, int texvres,
+        int hmeshlast, int vmeshlast, int ho, int vo, int sw, int sh)
+{
+    int x, y;
+    int x0, y0, x1, y1;
+    int u0, v0, u1, v1, u2, v2, u3, v3;
+    double xscale = 1.0 / ((double)(64 * texhres));
+    double yscale = 1.0 / ((double)(64 * texvres));
+
+    glLoadIdentity();
+    glTranslatef(ho, vo, 0);
+    glEnable(GL_TEXTURE_2D);
+    glBegin(GL_QUADS);
+
+    for (y = 0; y < vmeshlast; y++) {
+        y0 = y * sh;
+        y1 = y0 + sh;
+        for (x = 0; x < hmeshlast; x++) {
+            x0 = x * sw;
+            x1 = x0 + sw;
+
+            u0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].x);
+            v0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].y);
+            u1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].x);
+            v1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].y);
+            u2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].x);
+            v2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].y);
+            u3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].x);
+            v3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].y);
+
+            glTexCoord2d(((double)u0) * xscale, ((double)v0) * yscale);
+            glVertex3i(x0, y0, 0);
+            glTexCoord2d(((double)u1) * xscale, ((double)v1) * yscale);
+            glVertex3i(x1, y0, 0);
+            glTexCoord2d(((double)u2) * xscale, ((double)v2) * yscale);
+            glVertex3i(x1, y1, 0);
+            glTexCoord2d(((double)u3) * xscale, ((double)v3) * yscale);
+            glVertex3i(x0, y1, 0);
+        }
+    }
+
+    glEnd();
+}
+
+static void tmu2_start(MilkymistTMU2State *s)
+{
+    int pbuffer_attrib[6] = {
+        GLX_PBUFFER_WIDTH,
+        0,
+        GLX_PBUFFER_HEIGHT,
+        0,
+        GLX_PRESERVED_CONTENTS,
+        True
+    };
+
+    GLXPbuffer pbuffer;
+    GLuint texture;
+    void *fb;
+    target_phys_addr_t fb_len;
+    void *mesh;
+    target_phys_addr_t mesh_len;
+    float m;
+
+    trace_milkymist_tmu2_start();
+
+    /* Create and set up a suitable OpenGL context */
+    pbuffer_attrib[1] = s->regs[R_DSTHRES];
+    pbuffer_attrib[3] = s->regs[R_DSTVRES];
+    pbuffer = glXCreatePbuffer(s->dpy, s->glx_fb_config, pbuffer_attrib);
+    glXMakeContextCurrent(s->dpy, pbuffer, pbuffer, s->glx_context);
+
+    /* Fixup endianness. TODO: would it work on BE hosts? */
+    glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+    glPixelStorei(GL_PACK_SWAP_BYTES, 1);
+
+    /* Row alignment */
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
+    glPixelStorei(GL_PACK_ALIGNMENT, 2);
+
+    /* Read the QEMU source framebuffer into an OpenGL texture */
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    fb_len = 2*s->regs[R_TEXHRES]*s->regs[R_TEXVRES];
+    fb = cpu_physical_memory_map(s->regs[R_TEXFBUF], &fb_len, 0);
+    if (fb == NULL) {
+        glDeleteTextures(1, &texture);
+        glXMakeContextCurrent(s->dpy, None, None, NULL);
+        glXDestroyPbuffer(s->dpy, pbuffer);
+        return;
+    }
+    glTexImage2D(GL_TEXTURE_2D, 0, 3, s->regs[R_TEXHRES], s->regs[R_TEXVRES],
+            0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb);
+    cpu_physical_memory_unmap(fb, fb_len, 0, fb_len);
+
+    /* Set up texturing options */
+    /* WARNING:
+     * Many cases of TMU2 masking are not supported by OpenGL.
+     * We only implement the most common ones:
+     *  - full bilinear filtering vs. nearest texel
+     *  - texture clamping vs. texture wrapping
+     */
+    if ((s->regs[R_TEXHMASK] & 0x3f) > 0x20) {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    } else {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    }
+    if ((s->regs[R_TEXHMASK] >> 6) & s->regs[R_TEXHRES]) {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    } else {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    }
+    if ((s->regs[R_TEXVMASK] >> 6) & s->regs[R_TEXVRES]) {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+    } else {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    }
+
+    /* Translucency and decay */
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    m = (float)(s->regs[R_BRIGHTNESS] + 1) / 64.0f;
+    glColor4f(m, m, m, (float)(s->regs[R_ALPHA] + 1) / 64.0f);
+
+    /* Read the QEMU dest. framebuffer into the OpenGL framebuffer */
+    fb_len = 2 * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
+    fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 0);
+    if (fb == NULL) {
+        glDeleteTextures(1, &texture);
+        glXMakeContextCurrent(s->dpy, None, None, NULL);
+        glXDestroyPbuffer(s->dpy, pbuffer);
+        return;
+    }
+
+    glDrawPixels(s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB,
+            GL_UNSIGNED_SHORT_5_6_5, fb);
+    cpu_physical_memory_unmap(fb, fb_len, 0, fb_len);
+    glViewport(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES]);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(0.0, s->regs[R_DSTHRES], 0.0, s->regs[R_DSTVRES], -1.0, 1.0);
+    glMatrixMode(GL_MODELVIEW);
+
+    /* Map the texture */
+    mesh_len = MESH_MAXSIZE*MESH_MAXSIZE*sizeof(struct vertex);
+    mesh = cpu_physical_memory_map(s->regs[R_VERTICESADDR], &mesh_len, 0);
+    if (mesh == NULL) {
+        glDeleteTextures(1, &texture);
+        glXMakeContextCurrent(s->dpy, None, None, NULL);
+        glXDestroyPbuffer(s->dpy, pbuffer);
+        return;
+    }
+
+    tmu2_gl_map((struct vertex *)mesh,
+        s->regs[R_TEXHRES], s->regs[R_TEXVRES],
+        s->regs[R_HMESHLAST], s->regs[R_VMESHLAST],
+        s->regs[R_DSTHOFFSET], s->regs[R_DSTVOFFSET],
+        s->regs[R_DSTSQUAREW], s->regs[R_DSTSQUAREH]);
+    cpu_physical_memory_unmap(mesh, mesh_len, 0, mesh_len);
+
+    /* Write back the OpenGL framebuffer to the QEMU framebuffer */
+    fb_len = 2 * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
+    fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 1);
+    if (fb == NULL) {
+        glDeleteTextures(1, &texture);
+        glXMakeContextCurrent(s->dpy, None, None, NULL);
+        glXDestroyPbuffer(s->dpy, pbuffer);
+        return;
+    }
+
+    glReadPixels(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB,
+            GL_UNSIGNED_SHORT_5_6_5, fb);
+    cpu_physical_memory_unmap(fb, fb_len, 1, fb_len);
+
+    /* Free OpenGL allocs */
+    glDeleteTextures(1, &texture);
+    glXMakeContextCurrent(s->dpy, None, None, NULL);
+    glXDestroyPbuffer(s->dpy, pbuffer);
+
+    s->regs[R_CTL] &= ~CTL_START_BUSY;
+
+    trace_milkymist_tmu2_pulse_irq();
+    qemu_irq_pulse(s->irq);
+}
+
+static uint32_t tmu2_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistTMU2State *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTL:
+    case R_HMESHLAST:
+    case R_VMESHLAST:
+    case R_BRIGHTNESS:
+    case R_CHROMAKEY:
+    case R_VERTICESADDR:
+    case R_TEXFBUF:
+    case R_TEXHRES:
+    case R_TEXVRES:
+    case R_TEXHMASK:
+    case R_TEXVMASK:
+    case R_DSTFBUF:
+    case R_DSTHRES:
+    case R_DSTVRES:
+    case R_DSTHOFFSET:
+    case R_DSTVOFFSET:
+    case R_DSTSQUAREW:
+    case R_DSTSQUAREH:
+    case R_ALPHA:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_tmu2: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_tmu2_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void tmu2_check_registers(MilkymistTMU2State *s)
+{
+    if (s->regs[R_BRIGHTNESS] > MAX_BRIGHTNESS) {
+        error_report("milkymist_tmu2: max brightness is %d\n", MAX_BRIGHTNESS);
+    }
+
+    if (s->regs[R_ALPHA] > MAX_ALPHA) {
+        error_report("milkymist_tmu2: max alpha is %d\n", MAX_ALPHA);
+    }
+
+    if (s->regs[R_VERTICESADDR] & 0x07) {
+        error_report("milkymist_tmu2: vertex mesh address has to be 64-bit "
+                "aligned\n");
+    }
+
+    if (s->regs[R_TEXFBUF] & 0x01) {
+        error_report("milkymist_tmu2: texture buffer address has to be "
+                "16-bit aligned\n");
+    }
+}
+
+static void tmu2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistTMU2State *s = opaque;
+
+    trace_milkymist_tmu2_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTL:
+        s->regs[addr] = value;
+        if (value & CTL_START_BUSY) {
+            tmu2_start(s);
+        }
+        break;
+    case R_BRIGHTNESS:
+    case R_HMESHLAST:
+    case R_VMESHLAST:
+    case R_CHROMAKEY:
+    case R_VERTICESADDR:
+    case R_TEXFBUF:
+    case R_TEXHRES:
+    case R_TEXVRES:
+    case R_TEXHMASK:
+    case R_TEXVMASK:
+    case R_DSTFBUF:
+    case R_DSTHRES:
+    case R_DSTVRES:
+    case R_DSTHOFFSET:
+    case R_DSTVOFFSET:
+    case R_DSTSQUAREW:
+    case R_DSTSQUAREH:
+    case R_ALPHA:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_tmu2: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    tmu2_check_registers(s);
+}
+
+static CPUReadMemoryFunc * const tmu2_read_fn[] = {
+    NULL,
+    NULL,
+    &tmu2_read,
+};
+
+static CPUWriteMemoryFunc * const tmu2_write_fn[] = {
+    NULL,
+    NULL,
+    &tmu2_write,
+};
+
+static void milkymist_tmu2_reset(DeviceState *d)
+{
+    MilkymistTMU2State *s = container_of(d, MilkymistTMU2State, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+}
+
+static int milkymist_tmu2_init(SysBusDevice *dev)
+{
+    MilkymistTMU2State *s = FROM_SYSBUS(typeof(*s), dev);
+    int tmu2_regs;
+
+    if (tmu2_glx_init(s)) {
+        return 1;
+    }
+
+    sysbus_init_irq(dev, &s->irq);
+
+    tmu2_regs = cpu_register_io_memory(tmu2_read_fn, tmu2_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, tmu2_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_tmu2 = {
+    .name = "milkymist-tmu2",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistTMU2State, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_tmu2_info = {
+    .init = milkymist_tmu2_init,
+    .qdev.name  = "milkymist-tmu2",
+    .qdev.size  = sizeof(MilkymistTMU2State),
+    .qdev.vmsd  = &vmstate_milkymist_tmu2,
+    .qdev.reset = milkymist_tmu2_reset,
+};
+
+static void milkymist_tmu2_register(void)
+{
+    sysbus_register_withprop(&milkymist_tmu2_info);
+}
+
+device_init(milkymist_tmu2_register)
diff --git a/trace-events b/trace-events
index f6fc403..3a88adf 100644
--- a/trace-events
+++ b/trace-events
@@ -343,3 +343,9 @@ disable milkymist_sysctl_start_timer1(void) "Start timer1"
 disable milkymist_sysctl_stop_timer1(void) "Stop timer1"
 disable milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0"
 disable milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1"
+
+# hw/milkymist-tmu2.c
+disable milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_tmu2_start(void) "Start TMU"
+disable milkymist_tmu2_pulse_irq(void) "Pulse IRQ"
commit 20ff075bb3340c5278a0da38ad1f4d602565aa06
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:39 2011 +0100

    configure: add opengl detection
    
    This patch introduce a new config option CONFIG_OPENGL.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/configure b/configure
index 2e7b4f8..faaed60 100755
--- a/configure
+++ b/configure
@@ -720,6 +720,10 @@ for opt do
   ;;
   --enable-vhost-net) vhost_net="yes"
   ;;
+  --disable-opengl) opengl="no"
+  ;;
+  --enable-opengl) opengl="yes"
+  ;;
   --*dir)
   ;;
   --disable-rbd) rbd="no"
@@ -1944,6 +1948,27 @@ EOF
   fi
 fi
 
+##########################################
+# opengl probe, used by milkymist-tmu2
+if test "$opengl" != "no" ; then
+  opengl_libs="-lGL"
+  cat > $TMPC << EOF
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+int main(void) { GL_VERSION; return 0; }
+EOF
+  if compile_prog "" "-lGL" ; then
+    opengl=yes
+       libs_softmmu="$opengl_libs $libs_softmmu"
+  else
+    if test "$opengl" = "yes" ; then
+      feature_not_found "opengl"
+    fi
+    opengl=no
+  fi
+fi
+
 #
 # Check for xxxat() functions when we are building linux-user
 # emulator.  This is done because older glibc versions don't
@@ -2582,6 +2607,7 @@ echo "spice support     $spice"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
 echo "nss used          $smartcard_nss"
+echo "OpenGL support    $opengl"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2872,6 +2898,10 @@ if test "$smartcard_nss" = "yes" ; then
   echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
 fi
 
+if test "$opengl" = "yes" ; then
+  echo "CONFIG_OPENGL=y" >> $config_host_mak
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "CONFIG_BSD=y" >> $config_host_mak
commit 9683242448541b6fb5511421af3d8f0c6cd19477
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:38 2011 +0100

    lm32: add Milkymist System Controller support
    
    This patch adds support for Milkymist's System Controller core. The model
    has the following features:
     - support for shutting down and restarting the board
     - provide two timers and GPIO
     - provide registers for system identification and reading the boards
       capabilities
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 8924626..c117565 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -273,6 +273,7 @@ obj-lm32-y += milkymist-memcard.o
 obj-lm32-y += milkymist-minimac.o
 obj-lm32-y += milkymist-pfpu.o
 obj-lm32-y += milkymist-softusb.o
+obj-lm32-y += milkymist-sysctl.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
new file mode 100644
index 0000000..eaea543
--- /dev/null
+++ b/hw/milkymist-sysctl.c
@@ -0,0 +1,330 @@
+/*
+ *  QEMU model of the Milkymist System Controller.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/sysctl.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "sysemu.h"
+#include "trace.h"
+#include "qemu-timer.h"
+#include "qemu-error.h"
+
+enum {
+    CTRL_ENABLE      = (1<<0),
+    CTRL_AUTORESTART = (1<<1),
+};
+
+enum {
+    ICAP_READY       = (1<<0),
+};
+
+enum {
+    R_GPIO_IN = 0,
+    R_GPIO_OUT,
+    R_GPIO_INTEN,
+    R_RESERVED0,
+    R_TIMER0_CONTROL,
+    R_TIMER0_COMPARE,
+    R_TIMER0_COUNTER,
+    R_RESERVED1,
+    R_TIMER1_CONTROL,
+    R_TIMER1_COMPARE,
+    R_TIMER1_COUNTER,
+    R_RESERVED2,
+    R_RESERVED3,
+    R_ICAP,
+    R_CAPABILITIES,
+    R_SYSTEM_ID,
+    R_MAX
+};
+
+struct MilkymistSysctlState {
+    SysBusDevice busdev;
+
+    QEMUBH *bh0;
+    QEMUBH *bh1;
+    ptimer_state *ptimer0;
+    ptimer_state *ptimer1;
+
+    uint32_t freq_hz;
+    uint32_t capabilities;
+    uint32_t systemid;
+    uint32_t strappings;
+
+    uint32_t regs[R_MAX];
+
+    qemu_irq gpio_irq;
+    qemu_irq timer0_irq;
+    qemu_irq timer1_irq;
+};
+typedef struct MilkymistSysctlState MilkymistSysctlState;
+
+static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
+{
+    trace_milkymist_sysctl_icap_write(value);
+    switch (value & 0xffff) {
+    case 0x000e:
+        qemu_system_shutdown_request();
+        break;
+    }
+}
+
+static uint32_t sysctl_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistSysctlState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_TIMER0_COUNTER:
+        r = (uint32_t)ptimer_get_count(s->ptimer0);
+        /* milkymist timer counts up */
+        r = s->regs[R_TIMER0_COMPARE] - r;
+        break;
+    case R_TIMER1_COUNTER:
+        r = (uint32_t)ptimer_get_count(s->ptimer1);
+        /* milkymist timer counts up */
+        r = s->regs[R_TIMER1_COMPARE] - r;
+        break;
+    case R_GPIO_IN:
+    case R_GPIO_OUT:
+    case R_GPIO_INTEN:
+    case R_TIMER0_CONTROL:
+    case R_TIMER0_COMPARE:
+    case R_TIMER1_CONTROL:
+    case R_TIMER1_COMPARE:
+    case R_ICAP:
+    case R_CAPABILITIES:
+    case R_SYSTEM_ID:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_sysctl: read access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_sysctl_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistSysctlState *s = opaque;
+
+    trace_milkymist_sysctl_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_GPIO_OUT:
+    case R_GPIO_INTEN:
+    case R_TIMER0_COUNTER:
+        if (value > s->regs[R_TIMER0_COUNTER]) {
+            value = s->regs[R_TIMER0_COUNTER];
+            error_report("milkymist_sysctl: timer0: trying to write a "
+                    "value greater than the limit. Clipping.");
+        }
+        /* milkymist timer counts up */
+        value = s->regs[R_TIMER0_COUNTER] - value;
+        ptimer_set_count(s->ptimer0, value);
+        break;
+    case R_TIMER1_COUNTER:
+        if (value > s->regs[R_TIMER1_COUNTER]) {
+            value = s->regs[R_TIMER1_COUNTER];
+            error_report("milkymist_sysctl: timer1: trying to write a "
+                    "value greater than the limit. Clipping.");
+        }
+        /* milkymist timer counts up */
+        value = s->regs[R_TIMER1_COUNTER] - value;
+        ptimer_set_count(s->ptimer1, value);
+        break;
+    case R_TIMER0_COMPARE:
+        ptimer_set_limit(s->ptimer0, value, 0);
+        s->regs[addr] = value;
+        break;
+    case R_TIMER1_COMPARE:
+        ptimer_set_limit(s->ptimer1, value, 0);
+        s->regs[addr] = value;
+        break;
+    case R_TIMER0_CONTROL:
+        s->regs[addr] = value;
+        if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
+            trace_milkymist_sysctl_start_timer1();
+            ptimer_run(s->ptimer0, 0);
+        } else {
+            trace_milkymist_sysctl_stop_timer1();
+            ptimer_stop(s->ptimer0);
+        }
+        break;
+    case R_TIMER1_CONTROL:
+        s->regs[addr] = value;
+        if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
+            trace_milkymist_sysctl_start_timer1();
+            ptimer_run(s->ptimer1, 0);
+        } else {
+            trace_milkymist_sysctl_stop_timer1();
+            ptimer_stop(s->ptimer1);
+        }
+        break;
+    case R_ICAP:
+        sysctl_icap_write(s, value);
+        break;
+    case R_SYSTEM_ID:
+        qemu_system_reset_request();
+        break;
+
+    case R_GPIO_IN:
+    case R_CAPABILITIES:
+        error_report("milkymist_sysctl: write to read-only register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+
+    default:
+        error_report("milkymist_sysctl: write access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const sysctl_read_fn[] = {
+    NULL,
+    NULL,
+    &sysctl_read,
+};
+
+static CPUWriteMemoryFunc * const sysctl_write_fn[] = {
+    NULL,
+    NULL,
+    &sysctl_write,
+};
+
+static void timer0_hit(void *opaque)
+{
+    MilkymistSysctlState *s = opaque;
+
+    if (!(s->regs[R_TIMER0_CONTROL] & CTRL_AUTORESTART)) {
+        s->regs[R_TIMER0_CONTROL] &= ~CTRL_ENABLE;
+        trace_milkymist_sysctl_stop_timer0();
+        ptimer_stop(s->ptimer0);
+    }
+
+    trace_milkymist_sysctl_pulse_irq_timer0();
+    qemu_irq_pulse(s->timer0_irq);
+}
+
+static void timer1_hit(void *opaque)
+{
+    MilkymistSysctlState *s = opaque;
+
+    if (!(s->regs[R_TIMER1_CONTROL] & CTRL_AUTORESTART)) {
+        s->regs[R_TIMER1_CONTROL] &= ~CTRL_ENABLE;
+        trace_milkymist_sysctl_stop_timer1();
+        ptimer_stop(s->ptimer1);
+    }
+
+    trace_milkymist_sysctl_pulse_irq_timer1();
+    qemu_irq_pulse(s->timer1_irq);
+}
+
+static void milkymist_sysctl_reset(DeviceState *d)
+{
+    MilkymistSysctlState *s =
+            container_of(d, MilkymistSysctlState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    ptimer_stop(s->ptimer0);
+    ptimer_stop(s->ptimer1);
+
+    /* defaults */
+    s->regs[R_ICAP] = ICAP_READY;
+    s->regs[R_SYSTEM_ID] = s->systemid;
+    s->regs[R_CAPABILITIES] = s->capabilities;
+    s->regs[R_GPIO_IN] = s->strappings;
+}
+
+static int milkymist_sysctl_init(SysBusDevice *dev)
+{
+    MilkymistSysctlState *s = FROM_SYSBUS(typeof(*s), dev);
+    int sysctl_regs;
+
+    sysbus_init_irq(dev, &s->gpio_irq);
+    sysbus_init_irq(dev, &s->timer0_irq);
+    sysbus_init_irq(dev, &s->timer1_irq);
+
+    s->bh0 = qemu_bh_new(timer0_hit, s);
+    s->bh1 = qemu_bh_new(timer1_hit, s);
+    s->ptimer0 = ptimer_init(s->bh0);
+    s->ptimer1 = ptimer_init(s->bh1);
+    ptimer_set_freq(s->ptimer0, s->freq_hz);
+    ptimer_set_freq(s->ptimer1, s->freq_hz);
+
+    sysctl_regs = cpu_register_io_memory(sysctl_read_fn, sysctl_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, sysctl_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_sysctl = {
+    .name = "milkymist-sysctl",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistSysctlState, R_MAX),
+        VMSTATE_PTIMER(ptimer0, MilkymistSysctlState),
+        VMSTATE_PTIMER(ptimer1, MilkymistSysctlState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_sysctl_info = {
+    .init = milkymist_sysctl_init,
+    .qdev.name  = "milkymist-sysctl",
+    .qdev.size  = sizeof(MilkymistSysctlState),
+    .qdev.vmsd  = &vmstate_milkymist_sysctl,
+    .qdev.reset = milkymist_sysctl_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("frequency", MilkymistSysctlState,
+                freq_hz, 80000000),
+        DEFINE_PROP_UINT32("capabilities", MilkymistSysctlState,
+                capabilities, 0x00000000),
+        DEFINE_PROP_UINT32("systemid", MilkymistSysctlState,
+                systemid, 0x10014d31),
+        DEFINE_PROP_UINT32("gpio_strappings", MilkymistSysctlState,
+                strappings, 0x00000001),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void milkymist_sysctl_register(void)
+{
+    sysbus_register_withprop(&milkymist_sysctl_info);
+}
+
+device_init(milkymist_sysctl_register)
diff --git a/trace-events b/trace-events
index 74cce75..f6fc403 100644
--- a/trace-events
+++ b/trace-events
@@ -332,3 +332,14 @@ disable milkymist_softusb_mevt(uint8_t m) "m %d"
 disable milkymist_softusb_kevt(uint8_t m) "m %d"
 disable milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) "dx %d dy %d dz %d bs %02x"
 disable milkymist_softusb_pulse_irq(void) "Pulse IRQ"
+
+# hw/milkymist-sysctl.c
+disable milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_sysctl_icap_write(uint32_t value) "value %08x"
+disable milkymist_sysctl_start_timer0(void) "Start timer0"
+disable milkymist_sysctl_stop_timer0(void) "Stop timer0"
+disable milkymist_sysctl_start_timer1(void) "Start timer1"
+disable milkymist_sysctl_stop_timer1(void) "Stop timer1"
+disable milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0"
+disable milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1"
commit 87a381ec341bd0195db0531db10f29d603eff49a
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:37 2011 +0100

    lm32: add Milkymist SoftUSB support
    
    This patch adds support for Milkymist's SoftUSB core. This model differ
    from the real hardware in its functionality. The real hardware consits of a
    tiny freely programmable microcontroller which controls the USB ports. For
    simplicity reasons, this model emulates only keyboard and mouse input
    devices, eg. input events translates directly to the corresponding expected
    messages.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 0a87446..8924626 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -272,6 +272,7 @@ obj-lm32-y += milkymist-hpdmc.o
 obj-lm32-y += milkymist-memcard.o
 obj-lm32-y += milkymist-minimac.o
 obj-lm32-y += milkymist-pfpu.o
+obj-lm32-y += milkymist-softusb.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
new file mode 100644
index 0000000..1565260
--- /dev/null
+++ b/hw/milkymist-softusb.c
@@ -0,0 +1,357 @@
+/*
+ *  QEMU model of the Milkymist SoftUSB block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   not available yet
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "console.h"
+#include "usb.h"
+#include "qemu-error.h"
+
+enum {
+    R_CTRL = 0,
+    R_MAX
+};
+
+enum {
+    CTRL_RESET = (1<<0),
+};
+
+#define COMLOC_DEBUG_PRODUCE 0x1000
+#define COMLOC_DEBUG_BASE    0x1001
+#define COMLOC_MEVT_PRODUCE  0x1101
+#define COMLOC_MEVT_BASE     0x1102
+#define COMLOC_KEVT_PRODUCE  0x1142
+#define COMLOC_KEVT_BASE     0x1143
+
+struct MilkymistSoftUsbState {
+    SysBusDevice busdev;
+    USBBus usbbus;
+    USBPort usbport[2];
+    USBDevice *usbdev;
+
+    qemu_irq irq;
+
+    /* device properties */
+    uint32_t pmem_base;
+    uint32_t pmem_size;
+    uint32_t dmem_base;
+    uint32_t dmem_size;
+
+    /* device registers */
+    uint32_t regs[R_MAX];
+
+    /* mouse state */
+    int mouse_dx;
+    int mouse_dy;
+    int mouse_dz;
+    uint8_t mouse_buttons_state;
+
+    /* keyboard state */
+    uint8_t kbd_usb_buffer[8];
+};
+typedef struct MilkymistSoftUsbState MilkymistSoftUsbState;
+
+static uint32_t softusb_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistSoftUsbState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTRL:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_softusb: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_softusb_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void
+softusb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistSoftUsbState *s = opaque;
+
+    trace_milkymist_softusb_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTRL:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_softusb: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const softusb_read_fn[] = {
+    NULL,
+    NULL,
+    &softusb_read,
+};
+
+static CPUWriteMemoryFunc * const softusb_write_fn[] = {
+    NULL,
+    NULL,
+    &softusb_write,
+};
+
+static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
+        uint32_t offset, uint8_t *buf, uint32_t len)
+{
+    if (offset + len >= s->dmem_size) {
+        error_report("milkymist_softusb: read dmem out of bounds "
+                "at offset 0x%x, len %d\n", offset, len);
+        return;
+    }
+
+    cpu_physical_memory_read(s->dmem_base + offset, buf, len);
+}
+
+static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
+        uint32_t offset, uint8_t *buf, uint32_t len)
+{
+    if (offset + len >= s->dmem_size) {
+        error_report("milkymist_softusb: write dmem out of bounds "
+                "at offset 0x%x, len %d\n", offset, len);
+        return;
+    }
+
+    cpu_physical_memory_write(s->dmem_base + offset, buf, len);
+}
+
+static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
+        uint32_t offset, uint8_t *buf, uint32_t len)
+{
+    if (offset + len >= s->pmem_size) {
+        error_report("milkymist_softusb: read pmem out of bounds "
+                "at offset 0x%x, len %d\n", offset, len);
+        return;
+    }
+
+    cpu_physical_memory_read(s->pmem_base + offset, buf, len);
+}
+
+static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
+        uint32_t offset, uint8_t *buf, uint32_t len)
+{
+    if (offset + len >= s->pmem_size) {
+        error_report("milkymist_softusb: write pmem out of bounds "
+                "at offset 0x%x, len %d\n", offset, len);
+        return;
+    }
+
+    cpu_physical_memory_write(s->pmem_base + offset, buf, len);
+}
+
+static void softusb_mouse_changed(MilkymistSoftUsbState *s)
+{
+    uint8_t m;
+    uint8_t buf[4];
+
+    buf[0] = s->mouse_buttons_state;
+    buf[1] = s->mouse_dx;
+    buf[2] = s->mouse_dy;
+    buf[3] = s->mouse_dz;
+
+    softusb_read_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1);
+    trace_milkymist_softusb_mevt(m);
+    softusb_write_dmem(s, COMLOC_MEVT_BASE + 4 * m, buf, 4);
+    m = (m + 1) & 0xf;
+    softusb_write_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1);
+
+    trace_milkymist_softusb_pulse_irq();
+    qemu_irq_pulse(s->irq);
+}
+
+static void softusb_kbd_changed(MilkymistSoftUsbState *s)
+{
+    uint8_t m;
+
+    softusb_read_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1);
+    trace_milkymist_softusb_kevt(m);
+    softusb_write_dmem(s, COMLOC_KEVT_BASE + 8 * m, s->kbd_usb_buffer, 8);
+    m = (m + 1) & 0x7;
+    softusb_write_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1);
+
+    trace_milkymist_softusb_pulse_irq();
+    qemu_irq_pulse(s->irq);
+}
+
+static void softusb_mouse_event(void *opaque,
+       int dx, int dy, int dz, int buttons_state)
+{
+    MilkymistSoftUsbState *s = opaque;
+
+    /* if device is in reset, do nothing */
+    if (s->regs[R_CTRL] & CTRL_RESET) {
+        return;
+    }
+
+    trace_milkymist_softusb_mouse_event(dx, dy, dz, buttons_state);
+
+    s->mouse_dx = dx;
+    s->mouse_dy = dy;
+    s->mouse_dz = dz;
+    s->mouse_buttons_state = buttons_state;
+
+    softusb_mouse_changed(s);
+}
+
+static void softusb_usbdev_datain(void *opaque)
+{
+    MilkymistSoftUsbState *s = opaque;
+
+    USBPacket p;
+
+    p.pid = USB_TOKEN_IN;
+    p.devep = 1;
+    p.data = s->kbd_usb_buffer;
+    p.len = sizeof(s->kbd_usb_buffer);
+    s->usbdev->info->handle_data(s->usbdev, &p);
+
+    softusb_kbd_changed(s);
+}
+
+static void softusb_attach(USBPort *port)
+{
+}
+
+static USBPortOps softusb_ops = {
+    .attach = softusb_attach,
+};
+
+static void milkymist_softusb_reset(DeviceState *d)
+{
+    MilkymistSoftUsbState *s =
+            container_of(d, MilkymistSoftUsbState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    s->mouse_dx = 0;
+    s->mouse_dy = 0;
+    s->mouse_dz = 0;
+    s->mouse_buttons_state = 0;
+    memset(s->kbd_usb_buffer, 0, sizeof(s->kbd_usb_buffer));
+
+    /* defaults */
+    s->regs[R_CTRL] = CTRL_RESET;
+}
+
+static int milkymist_softusb_init(SysBusDevice *dev)
+{
+    MilkymistSoftUsbState *s = FROM_SYSBUS(typeof(*s), dev);
+    int softusb_regs;
+    ram_addr_t pmem_ram;
+    ram_addr_t dmem_ram;
+
+    sysbus_init_irq(dev, &s->irq);
+
+    softusb_regs = cpu_register_io_memory(softusb_read_fn, softusb_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, softusb_regs);
+
+    /* register pmem and dmem */
+    pmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.pmem", s->pmem_size);
+    cpu_register_physical_memory(s->pmem_base, s->pmem_size,
+            pmem_ram | IO_MEM_RAM);
+    dmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.dmem", s->dmem_size);
+    cpu_register_physical_memory(s->dmem_base, s->dmem_size,
+            dmem_ram | IO_MEM_RAM);
+
+    qemu_add_mouse_event_handler(softusb_mouse_event, s, 0, "Milkymist Mouse");
+
+    /* create our usb bus */
+    usb_bus_new(&s->usbbus, NULL);
+
+    /* our two ports */
+    usb_register_port(&s->usbbus, &s->usbport[0], NULL, 0, &softusb_ops,
+            USB_SPEED_MASK_LOW);
+    usb_register_port(&s->usbbus, &s->usbport[1], NULL, 1, &softusb_ops,
+            USB_SPEED_MASK_LOW);
+
+    /* and finally create an usb keyboard */
+    s->usbdev = usb_create_simple(&s->usbbus, "usb-kbd");
+    usb_hid_datain_cb(s->usbdev, s, softusb_usbdev_datain);
+    s->usbdev->info->handle_reset(s->usbdev);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_softusb = {
+    .name = "milkymist-softusb",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistSoftUsbState, R_MAX),
+        VMSTATE_INT32(mouse_dx, MilkymistSoftUsbState),
+        VMSTATE_INT32(mouse_dy, MilkymistSoftUsbState),
+        VMSTATE_INT32(mouse_dz, MilkymistSoftUsbState),
+        VMSTATE_UINT8(mouse_buttons_state, MilkymistSoftUsbState),
+        VMSTATE_BUFFER(kbd_usb_buffer, MilkymistSoftUsbState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_softusb_info = {
+    .init = milkymist_softusb_init,
+    .qdev.name  = "milkymist-softusb",
+    .qdev.size  = sizeof(MilkymistSoftUsbState),
+    .qdev.vmsd  = &vmstate_milkymist_softusb,
+    .qdev.reset = milkymist_softusb_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32(
+                "pmem_base", MilkymistSoftUsbState, pmem_base, 0xa0000000
+        ),
+        DEFINE_PROP_UINT32(
+                "pmem_size", MilkymistSoftUsbState, pmem_size, 0x00001000
+        ),
+        DEFINE_PROP_UINT32(
+                "dmem_base", MilkymistSoftUsbState, dmem_base, 0xa0020000
+        ),
+        DEFINE_PROP_UINT32(
+                "dmem_size", MilkymistSoftUsbState, dmem_size, 0x00002000
+        ),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void milkymist_softusb_register(void)
+{
+    sysbus_register_withprop(&milkymist_softusb_info);
+}
+
+device_init(milkymist_softusb_register)
diff --git a/trace-events b/trace-events
index b3fa971..74cce75 100644
--- a/trace-events
+++ b/trace-events
@@ -324,3 +324,11 @@ disable milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x val
 disable milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
 disable milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x"
 disable milkymist_pfpu_pulse_irq(void) "Pulse IRQ"
+
+# hw/milkymist-softusb.c
+disable milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_softusb_mevt(uint8_t m) "m %d"
+disable milkymist_softusb_kevt(uint8_t m) "m %d"
+disable milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) "dx %d dy %d dz %d bs %02x"
+disable milkymist_softusb_pulse_irq(void) "Pulse IRQ"
commit 5ee18b9c6843fa69da3c3ed92c57e01102614e34
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:36 2011 +0100

    lm32: add Milkymist PFPU support
    
    This patch adds support for Milkymist's Programmable FPU.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 6fd8a17..0a87446 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -271,6 +271,7 @@ obj-lm32-y += milkymist-ac97.o
 obj-lm32-y += milkymist-hpdmc.o
 obj-lm32-y += milkymist-memcard.o
 obj-lm32-y += milkymist-minimac.o
+obj-lm32-y += milkymist-pfpu.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
new file mode 100644
index 0000000..4831e00
--- /dev/null
+++ b/hw/milkymist-pfpu.c
@@ -0,0 +1,536 @@
+/*
+ *  QEMU model of the Milkymist programmable FPU.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/pfpu.pdf
+ *
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-log.h"
+#include "qemu-error.h"
+#include <math.h>
+
+/* #define TRACE_EXEC */
+
+#ifdef TRACE_EXEC
+#    define D_EXEC(x) x
+#else
+#    define D_EXEC(x)
+#endif
+
+enum {
+    R_CTL = 0,
+    R_MESHBASE,
+    R_HMESHLAST,
+    R_VMESHLAST,
+    R_CODEPAGE,
+    R_VERTICES,
+    R_COLLISIONS,
+    R_STRAYWRITES,
+    R_LASTDMA,
+    R_PC,
+    R_DREGBASE,
+    R_CODEBASE,
+    R_MAX
+};
+
+enum {
+    CTL_START_BUSY = (1<<0),
+};
+
+enum {
+    OP_NOP = 0,
+    OP_FADD,
+    OP_FSUB,
+    OP_FMUL,
+    OP_FABS,
+    OP_F2I,
+    OP_I2F,
+    OP_VECTOUT,
+    OP_SIN,
+    OP_COS,
+    OP_ABOVE,
+    OP_EQUAL,
+    OP_COPY,
+    OP_IF,
+    OP_TSIGN,
+    OP_QUAKE,
+};
+
+enum {
+    GPR_X = 0,
+    GPR_Y = 1,
+    GPR_FLAGS = 2,
+};
+
+enum {
+    LATENCY_FADD = 5,
+    LATENCY_FSUB = 5,
+    LATENCY_FMUL = 7,
+    LATENCY_FABS = 2,
+    LATENCY_F2I = 2,
+    LATENCY_I2F = 3,
+    LATENCY_VECTOUT = 0,
+    LATENCY_SIN = 4,
+    LATENCY_COS = 4,
+    LATENCY_ABOVE = 2,
+    LATENCY_EQUAL = 2,
+    LATENCY_COPY = 2,
+    LATENCY_IF = 2,
+    LATENCY_TSIGN = 2,
+    LATENCY_QUAKE = 2,
+    MAX_LATENCY = 7
+};
+
+#define GPR_BEGIN       0x100
+#define GPR_END         0x17f
+#define MICROCODE_BEGIN 0x200
+#define MICROCODE_END   0x3ff
+#define MICROCODE_WORDS 2048
+
+#define REINTERPRET_CAST(type, val) (*((type *)&(val)))
+
+#ifdef TRACE_EXEC
+static const char *opcode_to_str[] = {
+    "NOP", "FADD", "FSUB", "FMUL", "FABS", "F2I", "I2F", "VECTOUT",
+    "SIN", "COS", "ABOVE", "EQUAL", "COPY", "IF", "TSIGN", "QUAKE",
+};
+#endif
+
+struct MilkymistPFPUState {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint32_t regs[R_MAX];
+    uint32_t gp_regs[128];
+    uint32_t microcode[MICROCODE_WORDS];
+
+    int output_queue_pos;
+    uint32_t output_queue[MAX_LATENCY];
+};
+typedef struct MilkymistPFPUState MilkymistPFPUState;
+
+static inline target_phys_addr_t
+get_dma_address(uint32_t base, uint32_t x, uint32_t y)
+{
+    return base + 8 * (128 * y + x);
+}
+
+static inline void
+output_queue_insert(MilkymistPFPUState *s, uint32_t val, int pos)
+{
+    s->output_queue[(s->output_queue_pos + pos) % MAX_LATENCY] = val;
+}
+
+static inline uint32_t
+output_queue_remove(MilkymistPFPUState *s)
+{
+    return s->output_queue[s->output_queue_pos];
+}
+
+static inline void
+output_queue_advance(MilkymistPFPUState *s)
+{
+    s->output_queue[s->output_queue_pos] = 0;
+    s->output_queue_pos = (s->output_queue_pos + 1) % MAX_LATENCY;
+}
+
+static int pfpu_decode_insn(MilkymistPFPUState *s)
+{
+    uint32_t pc = s->regs[R_PC];
+    uint32_t insn = s->microcode[pc];
+    uint32_t reg_a = (insn >> 18) & 0x7f;
+    uint32_t reg_b = (insn >> 11) & 0x7f;
+    uint32_t op = (insn >> 7) & 0xf;
+    uint32_t reg_d = insn & 0x7f;
+    uint32_t r;
+    int latency = 0;
+
+    switch (op) {
+    case OP_NOP:
+        break;
+    case OP_FADD:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = a + b;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_FADD;
+        D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_FSUB:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = a - b;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_FSUB;
+        D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_FMUL:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = a * b;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_FMUL;
+        D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_FABS:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float t = fabsf(a);
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_FABS;
+        D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r));
+    } break;
+    case OP_F2I:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        int32_t t = a;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_F2I;
+        D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r));
+    } break;
+    case OP_I2F:
+    {
+        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
+        float t = a;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_I2F;
+        D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r));
+    } break;
+    case OP_VECTOUT:
+    {
+        uint32_t a = cpu_to_be32(s->gp_regs[reg_a]);
+        uint32_t b = cpu_to_be32(s->gp_regs[reg_b]);
+        target_phys_addr_t dma_ptr =
+            get_dma_address(s->regs[R_MESHBASE],
+                    s->gp_regs[GPR_X], s->gp_regs[GPR_Y]);
+        cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4);
+        cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&b, 4);
+        s->regs[R_LASTDMA] = dma_ptr + 4;
+        D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr));
+        trace_milkymist_pfpu_vectout(a, b, dma_ptr);
+    } break;
+    case OP_SIN:
+    {
+        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
+        float t = sinf(a * (1.0f / (M_PI * 4096.0f)));
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_SIN;
+        D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r));
+    } break;
+    case OP_COS:
+    {
+        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
+        float t = cosf(a * (1.0f / (M_PI * 4096.0f)));
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_COS;
+        D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r));
+    } break;
+    case OP_ABOVE:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = (a > b) ? 1.0f : 0.0f;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_ABOVE;
+        D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_EQUAL:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = (a == b) ? 1.0f : 0.0f;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_EQUAL;
+        D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_COPY:
+    {
+        r = s->gp_regs[reg_a];
+        latency = LATENCY_COPY;
+        D_EXEC(qemu_log("COPY"));
+    } break;
+    case OP_IF:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        uint32_t f = s->gp_regs[GPR_FLAGS];
+        float t = (f != 0) ? a : b;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_IF;
+        D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r));
+    } break;
+    case OP_TSIGN:
+    {
+        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
+        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
+        float t = (b < 0) ? -a : a;
+        r = REINTERPRET_CAST(uint32_t, t);
+        latency = LATENCY_TSIGN;
+        D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
+    } break;
+    case OP_QUAKE:
+    {
+        uint32_t a = s->gp_regs[reg_a];
+        r = 0x5f3759df - (a >> 1);
+        latency = LATENCY_QUAKE;
+        D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r));
+    } break;
+
+    default:
+        error_report("milkymist_pfpu: unknown opcode %d\n", op);
+        break;
+    }
+
+    if (!reg_d) {
+        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",
+                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,
+                    s->regs[R_PC] + latency));
+    } else {
+        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",
+                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,
+                    s->regs[R_PC] + latency, reg_d));
+    }
+
+    if (op == OP_VECTOUT) {
+        return 0;
+    }
+
+    /* store output for this cycle */
+    if (reg_d) {
+        uint32_t val = output_queue_remove(s);
+        D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val));
+        s->gp_regs[reg_d] = val;
+    }
+
+    output_queue_advance(s);
+
+    /* store op output */
+    if (op != OP_NOP) {
+        output_queue_insert(s, r, latency-1);
+    }
+
+    /* advance PC */
+    s->regs[R_PC]++;
+
+    return 1;
+};
+
+static void pfpu_start(MilkymistPFPUState *s)
+{
+    int x, y;
+    int i;
+
+    for (y = 0; y <= s->regs[R_VMESHLAST]; y++) {
+        for (x = 0; x <= s->regs[R_HMESHLAST]; x++) {
+            D_EXEC(qemu_log("\nprocessing x=%d y=%d\n", x, y));
+
+            /* set current position */
+            s->gp_regs[GPR_X] = x;
+            s->gp_regs[GPR_Y] = y;
+
+            /* run microcode on this position */
+            i = 0;
+            while (pfpu_decode_insn(s)) {
+                /* decode at most MICROCODE_WORDS instructions */
+                if (i++ >= MICROCODE_WORDS) {
+                    error_report("milkymist_pfpu: too many instructions "
+                            "executed in microcode. No VECTOUT?\n");
+                    break;
+                }
+            }
+
+            /* reset pc for next run */
+            s->regs[R_PC] = 0;
+        }
+    }
+
+    s->regs[R_VERTICES] = x * y;
+
+    trace_milkymist_pfpu_pulse_irq();
+    qemu_irq_pulse(s->irq);
+}
+
+static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr)
+{
+    return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN;
+}
+
+static uint32_t pfpu_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistPFPUState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTL:
+    case R_MESHBASE:
+    case R_HMESHLAST:
+    case R_VMESHLAST:
+    case R_CODEPAGE:
+    case R_VERTICES:
+    case R_COLLISIONS:
+    case R_STRAYWRITES:
+    case R_LASTDMA:
+    case R_PC:
+    case R_DREGBASE:
+    case R_CODEBASE:
+        r = s->regs[addr];
+        break;
+    case GPR_BEGIN ... GPR_END:
+        r = s->gp_regs[addr - GPR_BEGIN];
+        break;
+    case MICROCODE_BEGIN ...  MICROCODE_END:
+        r = s->microcode[get_microcode_address(s, addr)];
+        break;
+
+    default:
+        error_report("milkymist_pfpu: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_pfpu_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void
+pfpu_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistPFPUState *s = opaque;
+
+    trace_milkymist_pfpu_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTL:
+        if (value & CTL_START_BUSY) {
+            pfpu_start(s);
+        }
+        break;
+    case R_MESHBASE:
+    case R_HMESHLAST:
+    case R_VMESHLAST:
+    case R_CODEPAGE:
+    case R_VERTICES:
+    case R_COLLISIONS:
+    case R_STRAYWRITES:
+    case R_LASTDMA:
+    case R_PC:
+    case R_DREGBASE:
+    case R_CODEBASE:
+        s->regs[addr] = value;
+        break;
+    case GPR_BEGIN ...  GPR_END:
+        s->gp_regs[addr - GPR_BEGIN] = value;
+        break;
+    case MICROCODE_BEGIN ...  MICROCODE_END:
+        s->microcode[get_microcode_address(s, addr)] = value;
+        break;
+
+    default:
+        error_report("milkymist_pfpu: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const pfpu_read_fn[] = {
+    NULL,
+    NULL,
+    &pfpu_read,
+};
+
+static CPUWriteMemoryFunc * const pfpu_write_fn[] = {
+    NULL,
+    NULL,
+    &pfpu_write,
+};
+
+static void milkymist_pfpu_reset(DeviceState *d)
+{
+    MilkymistPFPUState *s = container_of(d, MilkymistPFPUState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    for (i = 0; i < 128; i++) {
+        s->gp_regs[i] = 0;
+    }
+    for (i = 0; i < MICROCODE_WORDS; i++) {
+        s->microcode[i] = 0;
+    }
+    s->output_queue_pos = 0;
+    for (i = 0; i < MAX_LATENCY; i++) {
+        s->output_queue[i] = 0;
+    }
+}
+
+static int milkymist_pfpu_init(SysBusDevice *dev)
+{
+    MilkymistPFPUState *s = FROM_SYSBUS(typeof(*s), dev);
+    int pfpu_regs;
+
+    sysbus_init_irq(dev, &s->irq);
+
+    pfpu_regs = cpu_register_io_memory(pfpu_read_fn, pfpu_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, MICROCODE_END * 4, pfpu_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_pfpu = {
+    .name = "milkymist-pfpu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistPFPUState, R_MAX),
+        VMSTATE_UINT32_ARRAY(gp_regs, MilkymistPFPUState, 128),
+        VMSTATE_UINT32_ARRAY(microcode, MilkymistPFPUState, MICROCODE_WORDS),
+        VMSTATE_INT32(output_queue_pos, MilkymistPFPUState),
+        VMSTATE_UINT32_ARRAY(output_queue, MilkymistPFPUState, MAX_LATENCY),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_pfpu_info = {
+    .init = milkymist_pfpu_init,
+    .qdev.name  = "milkymist-pfpu",
+    .qdev.size  = sizeof(MilkymistPFPUState),
+    .qdev.vmsd  = &vmstate_milkymist_pfpu,
+    .qdev.reset = milkymist_pfpu_reset,
+};
+
+static void milkymist_pfpu_register(void)
+{
+    sysbus_register_withprop(&milkymist_pfpu_info);
+}
+
+device_init(milkymist_pfpu_register)
diff --git a/trace-events b/trace-events
index 2becf85..b3fa971 100644
--- a/trace-events
+++ b/trace-events
@@ -318,3 +318,9 @@ disable milkymist_minimac_drop_rx_frame(const void *buf) "buf %p"
 disable milkymist_minimac_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
 disable milkymist_minimac_pulse_irq_rx(void) "Pulse IRQ RX"
 disable milkymist_minimac_pulse_irq_tx(void) "Pulse IRQ TX"
+
+# hw/milkymist-pfpu.c
+disable milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x"
+disable milkymist_pfpu_pulse_irq(void) "Pulse IRQ"
commit 0742454485d8fe5c88de390af0b20ce6c6e164b2
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:35 2011 +0100

    lm32: add Milkymist Minimac support
    
    This patch adds support for Milkymist's minimal Ethernet MAC.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index d58358b..6fd8a17 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -270,6 +270,7 @@ obj-lm32-y += lm32_sys.o
 obj-lm32-y += milkymist-ac97.o
 obj-lm32-y += milkymist-hpdmc.o
 obj-lm32-y += milkymist-memcard.o
+obj-lm32-y += milkymist-minimac.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-minimac.c b/hw/milkymist-minimac.c
new file mode 100644
index 0000000..b07f18d
--- /dev/null
+++ b/hw/milkymist-minimac.c
@@ -0,0 +1,568 @@
+/*
+ *  QEMU model of the Milkymist minimac block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/minimac.pdf
+ *
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "net.h"
+#include "qemu-error.h"
+
+#include <zlib.h>
+
+enum {
+    R_SETUP = 0,
+    R_MDIO,
+    R_STATE0,
+    R_ADDR0,
+    R_COUNT0,
+    R_STATE1,
+    R_ADDR1,
+    R_COUNT1,
+    R_STATE2,
+    R_ADDR2,
+    R_COUNT2,
+    R_STATE3,
+    R_ADDR3,
+    R_COUNT3,
+    R_TXADDR,
+    R_TXCOUNT,
+    R_MAX
+};
+
+enum {
+    SETUP_RX_RST = (1<<0),
+    SETUP_TX_RST = (1<<2),
+};
+
+enum {
+    MDIO_DO  = (1<<0),
+    MDIO_DI  = (1<<1),
+    MDIO_OE  = (1<<2),
+    MDIO_CLK = (1<<3),
+};
+
+enum {
+    STATE_EMPTY   = 0,
+    STATE_LOADED  = 1,
+    STATE_PENDING = 2,
+};
+
+enum {
+    MDIO_OP_WRITE = 1,
+    MDIO_OP_READ  = 2,
+};
+
+enum mdio_state {
+    MDIO_STATE_IDLE,
+    MDIO_STATE_READING,
+    MDIO_STATE_WRITING,
+};
+
+enum {
+    R_PHY_ID1  = 2,
+    R_PHY_ID2  = 3,
+    R_PHY_MAX  = 32
+};
+
+#define MINIMAC_MTU 1530
+
+struct MilkymistMinimacMdioState {
+    int last_clk;
+    int count;
+    uint32_t data;
+    uint16_t data_out;
+    int state;
+
+    uint8_t phy_addr;
+    uint8_t reg_addr;
+};
+typedef struct MilkymistMinimacMdioState MilkymistMinimacMdioState;
+
+struct MilkymistMinimacState {
+    SysBusDevice busdev;
+    NICState *nic;
+    NICConf conf;
+    char *phy_model;
+
+    qemu_irq rx_irq;
+    qemu_irq tx_irq;
+
+    uint32_t regs[R_MAX];
+
+    MilkymistMinimacMdioState mdio;
+
+    uint16_t phy_regs[R_PHY_MAX];
+};
+typedef struct MilkymistMinimacState MilkymistMinimacState;
+
+static const uint8_t preamble_sfd[] = {
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
+};
+
+static void minimac_mdio_write_reg(MilkymistMinimacState *s,
+        uint8_t phy_addr, uint8_t reg_addr, uint16_t value)
+{
+    trace_milkymist_minimac_mdio_write(phy_addr, reg_addr, value);
+
+    /* nop */
+}
+
+static uint16_t minimac_mdio_read_reg(MilkymistMinimacState *s,
+        uint8_t phy_addr, uint8_t reg_addr)
+{
+    uint16_t r = s->phy_regs[reg_addr];
+
+    trace_milkymist_minimac_mdio_read(phy_addr, reg_addr, r);
+
+    return r;
+}
+
+static void minimac_update_mdio(MilkymistMinimacState *s)
+{
+    MilkymistMinimacMdioState *m = &s->mdio;
+
+    /* detect rising clk edge */
+    if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) {
+        /* shift data in */
+        int bit = ((s->regs[R_MDIO] & MDIO_DO)
+                   && (s->regs[R_MDIO] & MDIO_OE)) ? 1 : 0;
+        m->data = (m->data << 1) | bit;
+
+        /* check for sync */
+        if (m->data == 0xffffffff) {
+            m->count = 32;
+        }
+
+        if (m->count == 16) {
+            uint8_t start = (m->data >> 14) & 0x3;
+            uint8_t op = (m->data >> 12) & 0x3;
+            uint8_t ta = (m->data) & 0x3;
+
+            if (start == 1 && op == MDIO_OP_WRITE && ta == 2) {
+                m->state = MDIO_STATE_WRITING;
+            } else if (start == 1 && op == MDIO_OP_READ && (ta & 1) == 0) {
+                m->state = MDIO_STATE_READING;
+            } else {
+                m->state = MDIO_STATE_IDLE;
+            }
+
+            if (m->state != MDIO_STATE_IDLE) {
+                m->phy_addr = (m->data >> 7) & 0x1f;
+                m->reg_addr = (m->data >> 2) & 0x1f;
+            }
+
+            if (m->state == MDIO_STATE_READING) {
+                m->data_out = minimac_mdio_read_reg(s, m->phy_addr,
+                        m->reg_addr);
+            }
+        }
+
+        if (m->count < 16 && m->state == MDIO_STATE_READING) {
+            int bit = (m->data_out & 0x8000) ? 1 : 0;
+            m->data_out <<= 1;
+
+            if (bit) {
+                s->regs[R_MDIO] |= MDIO_DI;
+            } else {
+                s->regs[R_MDIO] &= ~MDIO_DI;
+            }
+        }
+
+        if (m->count == 0 && m->state) {
+            if (m->state == MDIO_STATE_WRITING) {
+                uint16_t data = m->data & 0xffff;
+                minimac_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
+            }
+            m->state = MDIO_STATE_IDLE;
+        }
+        m->count--;
+    }
+
+    m->last_clk = (s->regs[R_MDIO] & MDIO_CLK) ? 1 : 0;
+}
+
+static size_t assemble_frame(uint8_t *buf, size_t size,
+        const uint8_t *payload, size_t payload_size)
+{
+    uint32_t crc;
+
+    if (size < payload_size + 12) {
+        error_report("milkymist_minimac: received too big ethernet frame");
+        return 0;
+    }
+
+    /* prepend preamble and sfd */
+    memcpy(buf, preamble_sfd, 8);
+
+    /* now copy the payload */
+    memcpy(buf + 8, payload, payload_size);
+
+    /* pad frame if needed */
+    if (payload_size < 60) {
+        memset(buf + payload_size + 8, 0, 60 - payload_size);
+        payload_size = 60;
+    }
+
+    /* append fcs */
+    crc = cpu_to_le32(crc32(0, buf + 8, payload_size));
+    memcpy(buf + payload_size + 8, &crc, 4);
+
+    return payload_size + 12;
+}
+
+static void minimac_tx(MilkymistMinimacState *s)
+{
+    uint8_t buf[MINIMAC_MTU];
+    uint32_t txcount = s->regs[R_TXCOUNT];
+
+    /* do nothing if transmission logic is in reset */
+    if (s->regs[R_SETUP] & SETUP_TX_RST) {
+        return;
+    }
+
+    if (txcount < 64) {
+        error_report("milkymist_minimac: ethernet frame too small (%u < %u)\n",
+                txcount, 64);
+        return;
+    }
+
+    if (txcount > MINIMAC_MTU) {
+        error_report("milkymist_minimac: MTU exceeded (%u > %u)\n",
+                txcount, MINIMAC_MTU);
+        return;
+    }
+
+    /* dma */
+    cpu_physical_memory_read(s->regs[R_TXADDR], buf, txcount);
+
+    if (memcmp(buf, preamble_sfd, 8) != 0) {
+        error_report("milkymist_minimac: frame doesn't contain the preamble "
+                "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n",
+                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+        return;
+    }
+
+    trace_milkymist_minimac_tx_frame(txcount - 12);
+
+    /* send packet, skipping preamble and sfd */
+    qemu_send_packet_raw(&s->nic->nc, buf + 8, txcount - 12);
+
+    s->regs[R_TXCOUNT] = 0;
+
+    trace_milkymist_minimac_pulse_irq_tx();
+    qemu_irq_pulse(s->tx_irq);
+}
+
+static ssize_t minimac_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    uint32_t r_addr;
+    uint32_t r_count;
+    uint32_t r_state;
+
+    uint8_t frame_buf[MINIMAC_MTU];
+    size_t frame_size;
+
+    trace_milkymist_minimac_rx_frame(buf, size);
+
+    /* discard frames if nic is in reset */
+    if (s->regs[R_SETUP] & SETUP_RX_RST) {
+        return size;
+    }
+
+    /* choose appropriate slot */
+    if (s->regs[R_STATE0] == STATE_LOADED) {
+        r_addr = R_ADDR0;
+        r_count = R_COUNT0;
+        r_state = R_STATE0;
+    } else if (s->regs[R_STATE1] == STATE_LOADED) {
+        r_addr = R_ADDR1;
+        r_count = R_COUNT1;
+        r_state = R_STATE1;
+    } else if (s->regs[R_STATE2] == STATE_LOADED) {
+        r_addr = R_ADDR2;
+        r_count = R_COUNT2;
+        r_state = R_STATE2;
+    } else if (s->regs[R_STATE3] == STATE_LOADED) {
+        r_addr = R_ADDR3;
+        r_count = R_COUNT3;
+        r_state = R_STATE3;
+    } else {
+        trace_milkymist_minimac_drop_rx_frame(buf);
+        return size;
+    }
+
+    /* assemble frame */
+    frame_size = assemble_frame(frame_buf, sizeof(frame_buf), buf, size);
+
+    if (frame_size == 0) {
+        return size;
+    }
+
+    trace_milkymist_minimac_rx_transfer(buf, frame_size);
+
+    /* do dma */
+    cpu_physical_memory_write(s->regs[r_addr], frame_buf, frame_size);
+
+    /* update slot */
+    s->regs[r_count] = frame_size;
+    s->regs[r_state] = STATE_PENDING;
+
+    trace_milkymist_minimac_pulse_irq_rx();
+    qemu_irq_pulse(s->rx_irq);
+
+    return size;
+}
+
+static uint32_t
+minimac_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistMinimacState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SETUP:
+    case R_MDIO:
+    case R_STATE0:
+    case R_ADDR0:
+    case R_COUNT0:
+    case R_STATE1:
+    case R_ADDR1:
+    case R_COUNT1:
+    case R_STATE2:
+    case R_ADDR2:
+    case R_COUNT2:
+    case R_STATE3:
+    case R_ADDR3:
+    case R_COUNT3:
+    case R_TXADDR:
+    case R_TXCOUNT:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_minimac: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_minimac_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void
+minimac_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistMinimacState *s = opaque;
+
+    trace_milkymist_minimac_memory_read(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_MDIO:
+    {
+        /* MDIO_DI is read only */
+        int mdio_di = (s->regs[R_MDIO] & MDIO_DI);
+        s->regs[R_MDIO] = value;
+        if (mdio_di) {
+            s->regs[R_MDIO] |= mdio_di;
+        } else {
+            s->regs[R_MDIO] &= ~mdio_di;
+        }
+
+        minimac_update_mdio(s);
+    } break;
+    case R_TXCOUNT:
+        s->regs[addr] = value;
+        if (value > 0) {
+            minimac_tx(s);
+        }
+        break;
+    case R_SETUP:
+    case R_STATE0:
+    case R_ADDR0:
+    case R_COUNT0:
+    case R_STATE1:
+    case R_ADDR1:
+    case R_COUNT1:
+    case R_STATE2:
+    case R_ADDR2:
+    case R_COUNT2:
+    case R_STATE3:
+    case R_ADDR3:
+    case R_COUNT3:
+    case R_TXADDR:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_minimac: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const minimac_read_fn[] = {
+    NULL,
+    NULL,
+    &minimac_read,
+};
+
+static CPUWriteMemoryFunc * const minimac_write_fn[] = {
+    NULL,
+    NULL,
+    &minimac_write,
+};
+
+static int minimac_can_rx(VLANClientState *nc)
+{
+    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* discard frames if nic is in reset */
+    if (s->regs[R_SETUP] & SETUP_RX_RST) {
+        return 1;
+    }
+
+    if (s->regs[R_STATE0] == STATE_LOADED) {
+        return 1;
+    }
+    if (s->regs[R_STATE1] == STATE_LOADED) {
+        return 1;
+    }
+    if (s->regs[R_STATE2] == STATE_LOADED) {
+        return 1;
+    }
+    if (s->regs[R_STATE3] == STATE_LOADED) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void minimac_cleanup(VLANClientState *nc)
+{
+    MilkymistMinimacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    s->nic = NULL;
+}
+
+static void milkymist_minimac_reset(DeviceState *d)
+{
+    MilkymistMinimacState *s =
+            container_of(d, MilkymistMinimacState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    for (i = 0; i < R_PHY_MAX; i++) {
+        s->phy_regs[i] = 0;
+    }
+
+    /* defaults */
+    s->phy_regs[R_PHY_ID1] = 0x0022; /* Micrel KSZ8001L */
+    s->phy_regs[R_PHY_ID2] = 0x161a;
+}
+
+static NetClientInfo net_milkymist_minimac_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = minimac_can_rx,
+    .receive = minimac_rx,
+    .cleanup = minimac_cleanup,
+};
+
+static int milkymist_minimac_init(SysBusDevice *dev)
+{
+    MilkymistMinimacState *s = FROM_SYSBUS(typeof(*s), dev);
+    int regs;
+
+    sysbus_init_irq(dev, &s->rx_irq);
+    sysbus_init_irq(dev, &s->tx_irq);
+
+    regs = cpu_register_io_memory(minimac_read_fn, minimac_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, regs);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_milkymist_minimac_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_minimac_mdio = {
+    .name = "milkymist_minimac_mdio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(last_clk, MilkymistMinimacMdioState),
+        VMSTATE_INT32(count, MilkymistMinimacMdioState),
+        VMSTATE_UINT32(data, MilkymistMinimacMdioState),
+        VMSTATE_UINT16(data_out, MilkymistMinimacMdioState),
+        VMSTATE_INT32(state, MilkymistMinimacMdioState),
+        VMSTATE_UINT8(phy_addr, MilkymistMinimacMdioState),
+        VMSTATE_UINT8(reg_addr, MilkymistMinimacMdioState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_milkymist_minimac = {
+    .name = "milkymist-minimac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistMinimacState, R_MAX),
+        VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimacState, R_PHY_MAX),
+        VMSTATE_STRUCT(mdio, MilkymistMinimacState, 0,
+                vmstate_milkymist_minimac_mdio, MilkymistMinimacMdioState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_minimac_info = {
+    .init = milkymist_minimac_init,
+    .qdev.name  = "milkymist-minimac",
+    .qdev.size  = sizeof(MilkymistMinimacState),
+    .qdev.vmsd  = &vmstate_milkymist_minimac,
+    .qdev.reset = milkymist_minimac_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(MilkymistMinimacState, conf),
+        DEFINE_PROP_STRING("phy_model", MilkymistMinimacState, phy_model),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void milkymist_minimac_register(void)
+{
+    sysbus_register_withprop(&milkymist_minimac_info);
+}
+
+device_init(milkymist_minimac_register)
diff --git a/trace-events b/trace-events
index 7627595..2becf85 100644
--- a/trace-events
+++ b/trace-events
@@ -306,3 +306,15 @@ disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x v
 # hw/milkymist-memcard.c
 disable milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
 disable milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+
+# hw/milkymist-minimac.c
+disable milkymist_minimac_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_minimac_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
+disable milkymist_minimac_tx_frame(uint32_t length) "length %u"
+disable milkymist_minimac_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
+disable milkymist_minimac_drop_rx_frame(const void *buf) "buf %p"
+disable milkymist_minimac_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
+disable milkymist_minimac_pulse_irq_rx(void) "Pulse IRQ RX"
+disable milkymist_minimac_pulse_irq_tx(void) "Pulse IRQ TX"
commit b4e37d98560c41afb944c616ce5c1df8577c35da
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:34 2011 +0100

    lm32: add Milkymist memory card support
    
    This patch adds support for Milkymist's memory card core.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 0e4f693..d58358b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -269,6 +269,7 @@ obj-lm32-y += lm32_uart.o
 obj-lm32-y += lm32_sys.o
 obj-lm32-y += milkymist-ac97.o
 obj-lm32-y += milkymist-hpdmc.o
+obj-lm32-y += milkymist-memcard.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/default-configs/lm32-softmmu.mak b/default-configs/lm32-softmmu.mak
index ab774a2..3e7f57e 100644
--- a/default-configs/lm32-softmmu.mak
+++ b/default-configs/lm32-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI02=y
+CONFIG_SD=y
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
new file mode 100644
index 0000000..06077af
--- /dev/null
+++ b/hw/milkymist-memcard.c
@@ -0,0 +1,294 @@
+/*
+ *  QEMU model of the Milkymist SD Card Controller.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/memcard.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "sysemu.h"
+#include "trace.h"
+#include "qemu-error.h"
+#include "blockdev.h"
+#include "sd.h"
+
+enum {
+    ENABLE_CMD_TX   = (1<<0),
+    ENABLE_CMD_RX   = (1<<1),
+    ENABLE_DAT_TX   = (1<<2),
+    ENABLE_DAT_RX   = (1<<3),
+};
+
+enum {
+    PENDING_CMD_TX   = (1<<0),
+    PENDING_CMD_RX   = (1<<1),
+    PENDING_DAT_TX   = (1<<2),
+    PENDING_DAT_RX   = (1<<3),
+};
+
+enum {
+    START_CMD_TX    = (1<<0),
+    START_DAT_RX    = (1<<1),
+};
+
+enum {
+    R_CLK2XDIV = 0,
+    R_ENABLE,
+    R_PENDING,
+    R_START,
+    R_CMD,
+    R_DAT,
+    R_MAX
+};
+
+struct MilkymistMemcardState {
+    SysBusDevice busdev;
+    SDState *card;
+
+    int command_write_ptr;
+    int response_read_ptr;
+    int response_len;
+    int ignore_next_cmd;
+    int enabled;
+    uint8_t command[6];
+    uint8_t response[17];
+    uint32_t regs[R_MAX];
+};
+typedef struct MilkymistMemcardState MilkymistMemcardState;
+
+static void update_pending_bits(MilkymistMemcardState *s)
+{
+    /* transmits are instantaneous, thus tx pending bits are never set */
+    s->regs[R_PENDING] = 0;
+    /* if rx is enabled the corresponding pending bits are always set */
+    if (s->regs[R_ENABLE] & ENABLE_CMD_RX) {
+        s->regs[R_PENDING] |= PENDING_CMD_RX;
+    }
+    if (s->regs[R_ENABLE] & ENABLE_DAT_RX) {
+        s->regs[R_PENDING] |= PENDING_DAT_RX;
+    }
+}
+
+static void memcard_sd_command(MilkymistMemcardState *s)
+{
+    SDRequest req;
+
+    req.cmd = s->command[0] & 0x3f;
+    req.arg = (s->command[1] << 24) | (s->command[2] << 16)
+              | (s->command[3] << 8) | s->command[4];
+    req.crc = s->command[5];
+
+    s->response[0] = req.cmd;
+    s->response_len = sd_do_command(s->card, &req, s->response+1);
+    s->response_read_ptr = 0;
+
+    if (s->response_len == 16) {
+        /* R2 response */
+        s->response[0] = 0x3f;
+        s->response_len += 1;
+    } else if (s->response_len == 4) {
+        /* no crc calculation, insert dummy byte */
+        s->response[5] = 0;
+        s->response_len += 2;
+    }
+
+    if (req.cmd == 0) {
+        /* next write is a dummy byte to clock the initialization of the sd
+         * card */
+        s->ignore_next_cmd = 1;
+    }
+}
+
+static uint32_t memcard_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistMemcardState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CMD:
+        if (!s->enabled) {
+            r = 0xff;
+        } else {
+            r = s->response[s->response_read_ptr++];
+            if (s->response_read_ptr > s->response_len) {
+                error_report("milkymist_memcard: "
+                        "read more cmd bytes than available. Clipping.");
+                s->response_read_ptr = 0;
+            }
+        }
+        break;
+    case R_DAT:
+        if (!s->enabled) {
+            r = 0xffffffff;
+        } else {
+            r = 0;
+            r |= sd_read_data(s->card) << 24;
+            r |= sd_read_data(s->card) << 16;
+            r |= sd_read_data(s->card) << 8;
+            r |= sd_read_data(s->card);
+        }
+        break;
+    case R_CLK2XDIV:
+    case R_ENABLE:
+    case R_PENDING:
+    case R_START:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_memcard: read access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_memcard_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void memcard_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistMemcardState *s = opaque;
+
+    trace_milkymist_memcard_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_PENDING:
+        /* clear rx pending bits */
+        s->regs[R_PENDING] &= ~(value & (PENDING_CMD_RX | PENDING_DAT_RX));
+        update_pending_bits(s);
+        break;
+    case R_CMD:
+        if (!s->enabled) {
+            break;
+        }
+        if (s->ignore_next_cmd) {
+            s->ignore_next_cmd = 0;
+            break;
+        }
+        s->command[s->command_write_ptr] = value & 0xff;
+        s->command_write_ptr = (s->command_write_ptr + 1) % 6;
+        if (s->command_write_ptr == 0) {
+            memcard_sd_command(s);
+        }
+        break;
+    case R_DAT:
+        if (!s->enabled) {
+            break;
+        }
+        sd_write_data(s->card, (value >> 24) & 0xff);
+        sd_write_data(s->card, (value >> 16) & 0xff);
+        sd_write_data(s->card, (value >> 8) & 0xff);
+        sd_write_data(s->card, value & 0xff);
+        break;
+    case R_ENABLE:
+        s->regs[addr] = value;
+        update_pending_bits(s);
+        break;
+    case R_CLK2XDIV:
+    case R_START:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_memcard: write access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const memcard_read_fn[] = {
+    NULL,
+    NULL,
+    &memcard_read,
+};
+
+static CPUWriteMemoryFunc * const memcard_write_fn[] = {
+    NULL,
+    NULL,
+    &memcard_write,
+};
+
+static void milkymist_memcard_reset(DeviceState *d)
+{
+    MilkymistMemcardState *s =
+            container_of(d, MilkymistMemcardState, busdev.qdev);
+    int i;
+
+    s->command_write_ptr = 0;
+    s->response_read_ptr = 0;
+    s->response_len = 0;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+}
+
+static int milkymist_memcard_init(SysBusDevice *dev)
+{
+    MilkymistMemcardState *s = FROM_SYSBUS(typeof(*s), dev);
+    DriveInfo *dinfo;
+    int memcard_regs;
+
+    dinfo = drive_get_next(IF_SD);
+    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
+    s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
+
+    memcard_regs = cpu_register_io_memory(memcard_read_fn, memcard_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, memcard_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_memcard = {
+    .name = "milkymist-memcard",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT32(command_write_ptr, MilkymistMemcardState),
+        VMSTATE_INT32(response_read_ptr, MilkymistMemcardState),
+        VMSTATE_INT32(response_len, MilkymistMemcardState),
+        VMSTATE_INT32(ignore_next_cmd, MilkymistMemcardState),
+        VMSTATE_INT32(enabled, MilkymistMemcardState),
+        VMSTATE_UINT8_ARRAY(command, MilkymistMemcardState, 6),
+        VMSTATE_UINT8_ARRAY(response, MilkymistMemcardState, 17),
+        VMSTATE_UINT32_ARRAY(regs, MilkymistMemcardState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_memcard_info = {
+    .init = milkymist_memcard_init,
+    .qdev.name  = "milkymist-memcard",
+    .qdev.size  = sizeof(MilkymistMemcardState),
+    .qdev.vmsd  = &vmstate_milkymist_memcard,
+    .qdev.reset = milkymist_memcard_reset,
+};
+
+static void milkymist_memcard_register(void)
+{
+    sysbus_register_withprop(&milkymist_memcard_info);
+}
+
+device_init(milkymist_memcard_register)
diff --git a/trace-events b/trace-events
index 9ccf82c..7627595 100644
--- a/trace-events
+++ b/trace-events
@@ -300,5 +300,9 @@ disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %
 disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
 
 # hw/milkymist-hpdmc.c
-disable milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=%08x value=%08x"
+disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x value=%08x"
+
+# hw/milkymist-memcard.c
+disable milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
commit e4dc6d2cdca3e64fe09d3c76a56294b7b7aa7d7f
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:33 2011 +0100

    lm32: add Milkymist HPDMC support
    
    This patch adds support for the Milkymist's High Performance Dynamic Memory
    Controller. This is just a dumb model without any functionality. While the
    real hardware acts for example as a bridge between software and hardware
    for sending SDRAM commans, this model will only eat up these commands and
    always returns the expected hardware states, eg. PLL locked etc.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 0610bb8..0e4f693 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -268,6 +268,7 @@ obj-lm32-y += lm32_timer.o
 obj-lm32-y += lm32_uart.o
 obj-lm32-y += lm32_sys.o
 obj-lm32-y += milkymist-ac97.o
+obj-lm32-y += milkymist-hpdmc.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
new file mode 100644
index 0000000..c0962fb
--- /dev/null
+++ b/hw/milkymist-hpdmc.c
@@ -0,0 +1,161 @@
+/*
+ *  QEMU model of the Milkymist High Performance Dynamic Memory Controller.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/hpdmc.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-error.h"
+
+enum {
+    R_SYSTEM = 0,
+    R_BYPASS,
+    R_TIMING,
+    R_IODELAY,
+    R_MAX
+};
+
+enum {
+    IODELAY_DQSDELAY_RDY = (1<<5),
+    IODELAY_PLL1_LOCKED  = (1<<6),
+    IODELAY_PLL2_LOCKED  = (1<<7),
+};
+
+struct MilkymistHpdmcState {
+    SysBusDevice busdev;
+
+    uint32_t regs[R_MAX];
+};
+typedef struct MilkymistHpdmcState MilkymistHpdmcState;
+
+static uint32_t hpdmc_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistHpdmcState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SYSTEM:
+    case R_BYPASS:
+    case R_TIMING:
+    case R_IODELAY:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_hpdmc: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_hpdmc_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistHpdmcState *s = opaque;
+
+    trace_milkymist_hpdmc_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SYSTEM:
+    case R_BYPASS:
+    case R_TIMING:
+        s->regs[addr] = value;
+        break;
+    case R_IODELAY:
+        /* ignore writes */
+        break;
+
+    default:
+        error_report("milkymist_hpdmc: write access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const hpdmc_read_fn[] = {
+    NULL,
+    NULL,
+    &hpdmc_read,
+};
+
+static CPUWriteMemoryFunc * const hpdmc_write_fn[] = {
+    NULL,
+    NULL,
+    &hpdmc_write,
+};
+
+static void milkymist_hpdmc_reset(DeviceState *d)
+{
+    MilkymistHpdmcState *s = container_of(d, MilkymistHpdmcState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    /* defaults */
+    s->regs[R_IODELAY] = IODELAY_DQSDELAY_RDY | IODELAY_PLL1_LOCKED
+                         | IODELAY_PLL2_LOCKED;
+}
+
+static int milkymist_hpdmc_init(SysBusDevice *dev)
+{
+    MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev);
+    int hpdmc_regs;
+
+    hpdmc_regs = cpu_register_io_memory(hpdmc_read_fn, hpdmc_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, hpdmc_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_hpdmc = {
+    .name = "milkymist-hpdmc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistHpdmcState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_hpdmc_info = {
+    .init = milkymist_hpdmc_init,
+    .qdev.name  = "milkymist-hpdmc",
+    .qdev.size  = sizeof(MilkymistHpdmcState),
+    .qdev.vmsd  = &vmstate_milkymist_hpdmc,
+    .qdev.reset = milkymist_hpdmc_reset,
+};
+
+static void milkymist_hpdmc_register(void)
+{
+    sysbus_register_withprop(&milkymist_hpdmc_info);
+}
+
+device_init(milkymist_hpdmc_register)
diff --git a/trace-events b/trace-events
index fc8caa8..9ccf82c 100644
--- a/trace-events
+++ b/trace-events
@@ -298,3 +298,7 @@ disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining
 disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
 disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
 disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
+
+# hw/milkymist-hpdmc.c
+disable milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
commit 25a8bb96f4a9dcb27dc55027b81d9646273a937b
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:32:32 2011 +0100

    lm32: add Milkymist AC97 support
    
    This patch adds support for the Milkymist AC97 compatible sound output and
    input core.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 04e20dd..0610bb8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -267,6 +267,7 @@ obj-lm32-y += lm32_juart.o
 obj-lm32-y += lm32_timer.o
 obj-lm32-y += lm32_uart.o
 obj-lm32-y += lm32_sys.o
+obj-lm32-y += milkymist-ac97.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/configure b/configure
index e91525f..2e7b4f8 100755
--- a/configure
+++ b/configure
@@ -3350,6 +3350,9 @@ if test "$target_softmmu" = "yes" ; then
   arm)
     cflags="-DHAS_AUDIO $cflags"
   ;;
+  lm32)
+    cflags="-DHAS_AUDIO $cflags"
+  ;;
   i386|mips|ppc)
     cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags"
   ;;
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
new file mode 100644
index 0000000..6c9e318
--- /dev/null
+++ b/hw/milkymist-ac97.c
@@ -0,0 +1,335 @@
+/*
+ *  QEMU model of the Milkymist System Controller.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/ac97.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "audio/audio.h"
+#include "qemu-error.h"
+
+enum {
+    R_AC97_CTRL = 0,
+    R_AC97_ADDR,
+    R_AC97_DATAOUT,
+    R_AC97_DATAIN,
+    R_D_CTRL,
+    R_D_ADDR,
+    R_D_REMAINING,
+    R_RESERVED,
+    R_U_CTRL,
+    R_U_ADDR,
+    R_U_REMAINING,
+    R_MAX
+};
+
+enum {
+    AC97_CTRL_RQEN  = (1<<0),
+    AC97_CTRL_WRITE = (1<<1),
+};
+
+enum {
+    CTRL_EN = (1<<0),
+};
+
+struct MilkymistAC97State {
+    SysBusDevice busdev;
+
+    QEMUSoundCard card;
+    SWVoiceIn *voice_in;
+    SWVoiceOut *voice_out;
+
+    uint32_t regs[R_MAX];
+
+    qemu_irq crrequest_irq;
+    qemu_irq crreply_irq;
+    qemu_irq dmar_irq;
+    qemu_irq dmaw_irq;
+};
+typedef struct MilkymistAC97State MilkymistAC97State;
+
+static void update_voices(MilkymistAC97State *s)
+{
+    if (s->regs[R_D_CTRL] & CTRL_EN) {
+        AUD_set_active_out(s->voice_out, 1);
+    } else {
+        AUD_set_active_out(s->voice_out, 0);
+    }
+
+    if (s->regs[R_U_CTRL] & CTRL_EN) {
+        AUD_set_active_in(s->voice_in, 1);
+    } else {
+        AUD_set_active_in(s->voice_in, 0);
+    }
+}
+
+static uint32_t ac97_read(void *opaque, target_phys_addr_t addr)
+{
+    MilkymistAC97State *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_AC97_CTRL:
+    case R_AC97_ADDR:
+    case R_AC97_DATAOUT:
+    case R_AC97_DATAIN:
+    case R_D_CTRL:
+    case R_D_ADDR:
+    case R_D_REMAINING:
+    case R_U_CTRL:
+    case R_U_ADDR:
+    case R_U_REMAINING:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_ac97: read access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_ac97_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    MilkymistAC97State *s = opaque;
+
+    trace_milkymist_ac97_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_AC97_CTRL:
+        /* always raise an IRQ according to the direction */
+        if (value & AC97_CTRL_RQEN) {
+            if (value & AC97_CTRL_WRITE) {
+                trace_milkymist_ac97_pulse_irq_crrequest();
+                qemu_irq_pulse(s->crrequest_irq);
+            } else {
+                trace_milkymist_ac97_pulse_irq_crreply();
+                qemu_irq_pulse(s->crreply_irq);
+            }
+        }
+
+        /* RQEN is self clearing */
+        s->regs[addr] = value & ~AC97_CTRL_RQEN;
+        break;
+    case R_D_CTRL:
+    case R_U_CTRL:
+        s->regs[addr] = value;
+        update_voices(s);
+        break;
+    case R_AC97_ADDR:
+    case R_AC97_DATAOUT:
+    case R_AC97_DATAIN:
+    case R_D_ADDR:
+    case R_D_REMAINING:
+    case R_U_ADDR:
+    case R_U_REMAINING:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_ac97: write access to unkown register 0x"
+                TARGET_FMT_plx, addr);
+        break;
+    }
+
+}
+
+static CPUReadMemoryFunc * const ac97_read_fn[] = {
+    NULL,
+    NULL,
+    &ac97_read,
+};
+
+static CPUWriteMemoryFunc * const ac97_write_fn[] = {
+    NULL,
+    NULL,
+    &ac97_write,
+};
+
+static void ac97_in_cb(void *opaque, int avail_b)
+{
+    MilkymistAC97State *s = opaque;
+    uint8_t buf[4096];
+    uint32_t remaining = s->regs[R_U_REMAINING];
+    int temp = audio_MIN(remaining, avail_b);
+    uint32_t addr = s->regs[R_U_ADDR];
+    int transferred = 0;
+
+    trace_milkymist_ac97_in_cb(avail_b, remaining);
+
+    /* prevent from raising an IRQ */
+    if (temp == 0) {
+        return;
+    }
+
+    while (temp) {
+        int acquired, to_copy;
+
+        to_copy = audio_MIN(temp, sizeof(buf));
+        acquired = AUD_read(s->voice_in, buf, to_copy);
+        if (!acquired) {
+            break;
+        }
+
+        cpu_physical_memory_write(addr, buf, acquired);
+
+        temp -= acquired;
+        addr += acquired;
+        transferred += acquired;
+    }
+
+    trace_milkymist_ac97_in_cb_transferred(transferred);
+
+    s->regs[R_U_ADDR] = addr;
+    s->regs[R_U_REMAINING] -= transferred;
+
+    if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) {
+        trace_milkymist_ac97_pulse_irq_dmaw();
+        qemu_irq_pulse(s->dmaw_irq);
+    }
+}
+
+static void ac97_out_cb(void *opaque, int free_b)
+{
+    MilkymistAC97State *s = opaque;
+    uint8_t buf[4096];
+    uint32_t remaining = s->regs[R_D_REMAINING];
+    int temp = audio_MIN(remaining, free_b);
+    uint32_t addr = s->regs[R_D_ADDR];
+    int transferred = 0;
+
+    trace_milkymist_ac97_out_cb(free_b, remaining);
+
+    /* prevent from raising an IRQ */
+    if (temp == 0) {
+        return;
+    }
+
+    while (temp) {
+        int copied, to_copy;
+
+        to_copy = audio_MIN(temp, sizeof(buf));
+        cpu_physical_memory_read(addr, buf, to_copy);
+        copied = AUD_write(s->voice_out, buf, to_copy);
+        if (!copied) {
+            break;
+        }
+        temp -= copied;
+        addr += copied;
+        transferred += copied;
+    }
+
+    trace_milkymist_ac97_out_cb_transferred(transferred);
+
+    s->regs[R_D_ADDR] = addr;
+    s->regs[R_D_REMAINING] -= transferred;
+
+    if ((s->regs[R_D_CTRL] & CTRL_EN) && (s->regs[R_D_REMAINING] == 0)) {
+        trace_milkymist_ac97_pulse_irq_dmar();
+        qemu_irq_pulse(s->dmar_irq);
+    }
+}
+
+static void milkymist_ac97_reset(DeviceState *d)
+{
+    MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    AUD_set_active_in(s->voice_in, 0);
+    AUD_set_active_out(s->voice_out, 0);
+}
+
+static int ac97_post_load(void *opaque, int version_id)
+{
+    MilkymistAC97State *s = opaque;
+
+    update_voices(s);
+
+    return 0;
+}
+
+static int milkymist_ac97_init(SysBusDevice *dev)
+{
+    MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
+    int ac97_regs;
+
+    struct audsettings as;
+    sysbus_init_irq(dev, &s->crrequest_irq);
+    sysbus_init_irq(dev, &s->crreply_irq);
+    sysbus_init_irq(dev, &s->dmar_irq);
+    sysbus_init_irq(dev, &s->dmaw_irq);
+
+    AUD_register_card("Milkymist AC'97", &s->card);
+
+    as.freq = 48000;
+    as.nchannels = 2;
+    as.fmt = AUD_FMT_S16;
+    as.endianness = 1;
+
+    s->voice_in = AUD_open_in(&s->card, s->voice_in,
+            "mm_ac97.in", s, ac97_in_cb, &as);
+    s->voice_out = AUD_open_out(&s->card, s->voice_out,
+            "mm_ac97.out", s, ac97_out_cb, &as);
+
+    ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, ac97_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_ac97 = {
+    .name = "milkymist-ac97",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ac97_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo milkymist_ac97_info = {
+    .init = milkymist_ac97_init,
+    .qdev.name  = "milkymist-ac97",
+    .qdev.size  = sizeof(MilkymistAC97State),
+    .qdev.vmsd  = &vmstate_milkymist_ac97,
+    .qdev.reset = milkymist_ac97_reset,
+};
+
+static void milkymist_ac97_register(void)
+{
+    sysbus_register_withprop(&milkymist_ac97_info);
+}
+
+device_init(milkymist_ac97_register)
diff --git a/trace-events b/trace-events
index 90c9e0b..fc8caa8 100644
--- a/trace-events
+++ b/trace-events
@@ -286,3 +286,15 @@ disable lm32_uart_irq_state(int level) "irq state %d"
 
 # hw/lm32_sys.c
 disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+
+# hw/milkymist-ac97.c
+disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request"
+disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply"
+disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write"
+disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read"
+disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u"
+disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
+disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
+disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
commit 449aa4a4915f4d2f43126eec6031cfc96ef06687
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 4 07:14:03 2011 +0200

    Revert "ioapic: when switches to level trigger mode, interrupts raised repeatedly."
    
    This reverts commit 9bcfc7daabb138b0fe3d64d74892942d482e5bbd.

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 8557e5c..569327d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -164,7 +164,6 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
             if (level) {
                 s->irr |= mask;
                 ioapic_service(s);
-                s->irr &= ~mask;
             }
         }
     }
commit 490f4edcdf64524fb29a758e381985b6b0cf002f
Author: Ulrich Hecht <uli at suse.de>
Date:   Tue Mar 29 15:29:34 2011 +0200

    s390x: enable CPU_QuadU
    
    S390x uses the QuadU type, so let's enable it.
    
    Signed-off-by: Ulrich Hecht <uli at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-all.h b/cpu-all.h
index 4f4631d..4cc445f 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -138,7 +138,7 @@ typedef union {
     uint64_t ll;
 } CPU_DoubleU;
 
-#ifdef TARGET_SPARC
+#if defined(TARGET_SPARC) || defined(TARGET_S390X)
 typedef union {
     float128 q;
 #if defined(HOST_WORDS_BIGENDIAN) \
commit bc434676dc99f492492b8d0b23a0e49262202029
Author: Ulrich Hecht <uli at suse.de>
Date:   Tue Mar 29 15:29:33 2011 +0200

    s390x: Enable nptl for s390x
    
    S390x user emulation can do nptl. Reflect this in the configure script.
    
    Signed-off-by: Ulrich Hecht <uli at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 2ef5c75..e91525f 100755
--- a/configure
+++ b/configure
@@ -3150,6 +3150,7 @@ case "$target_arch2" in
     target_phys_bits=64
   ;;
   s390x)
+    target_nptl="yes"
     target_phys_bits=64
   ;;
   *)
commit db500609847caa9d43a1186bb7ab2df56fa8e1b0
Author: Ulrich Hecht <uli at suse.de>
Date:   Tue Mar 29 15:29:32 2011 +0200

    s390x: Enable disassembler for s390x
    
    This patch enables the instruction disassembler when using an
    S390x target.
    
    Signed-off-by: Ulrich Hecht <uli at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/disas.c b/disas.c
index c76f36f..17b4ce4 100644
--- a/disas.c
+++ b/disas.c
@@ -215,6 +215,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
         disasm_info.mach = bfd_mach_cris_v32;
         print_insn = print_insn_crisv32;
     }
+#elif defined(TARGET_S390X)
+    disasm_info.mach = bfd_mach_s390_64;
+    print_insn = print_insn_s390;
 #elif defined(TARGET_MICROBLAZE)
     disasm_info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
@@ -414,6 +417,9 @@ void monitor_disas(Monitor *mon, CPUState *env,
 #elif defined(TARGET_SH4)
     disasm_info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
+#elif defined(TARGET_S390X)
+    disasm_info.mach = bfd_mach_s390_64;
+    print_insn = print_insn_s390;
 #else
     monitor_printf(mon, "0x" TARGET_FMT_lx
                    ": Asm output not supported on this arch\n", pc);
commit 6be9b4147adb27f78ec944af5abfc97e7cd0d066
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Mar 29 15:29:31 2011 +0200

    s390x: fix s390-virtio-serial
    
    Commit 6b331efb733a0f913ddc0b7762a1307dec304061 broke the s390 proxy version
    of virtio-serial by only taking its PCI brother into account.
    
    So let's adjust s390-virtio-serial the same way as its PCI counterpart, making
    it compile and work again.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    CC: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index d44eff2..58af164 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -139,7 +139,7 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev)
 
     bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
 
-    vdev = virtio_serial_init((DeviceState *)dev, dev->max_virtserial_ports);
+    vdev = virtio_serial_init((DeviceState *)dev, &dev->serial);
     if (!vdev) {
         return -1;
     }
@@ -355,8 +355,8 @@ static VirtIOS390DeviceInfo s390_virtio_serial = {
     .qdev.alias = "virtio-serial",
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("max_ports", VirtIOS390Device, max_virtserial_ports,
-                           31),
+        DEFINE_PROP_UINT32("max_ports", VirtIOS390Device,
+                           serial.max_virtserial_ports, 31),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 33379a3..edf6d04 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -18,6 +18,7 @@
  */
 
 #include "virtio-net.h"
+#include "virtio-serial.h"
 
 #define VIRTIO_DEV_OFFS_TYPE		0	/* 8 bits */
 #define VIRTIO_DEV_OFFS_NUM_VQ		1	/* 8 bits */
@@ -43,8 +44,7 @@ typedef struct VirtIOS390Device {
     BlockConf block;
     NICConf nic;
     uint32_t host_features;
-    /* Max. number of ports we can have for a the virtio-serial device */
-    uint32_t max_virtserial_ports;
+    virtio_serial_conf serial;
     virtio_net_conf net;
 } VirtIOS390Device;
 
commit 359507eed1b6d8ae2392e0c8fe32d5f0de9d1d75
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Mar 29 15:29:30 2011 +0200

    s390x: fix KVM target
    
    During Jan's rework of the generic KVM layer, he added some more error checks
    and actually aborted if something went wrong. Unfortunately, one of the s390
    internal error codes slipped through, aborting the VM without needing to.
    
    This patch fixes booting of S390x virtual machines in KVM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    CC: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 9123203..ae7dc56 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -441,7 +441,7 @@ static int handle_instruction(CPUState *env, struct kvm_run *run)
     if (r < 0) {
         enter_pgmcheck(env, 0x0001);
     }
-    return r;
+    return 0;
 }
 
 static int handle_intercept(CPUState *env)
commit 29f82b37e5341b96e514373854411c4fcb935fc0
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Mar 29 15:29:29 2011 +0200

    virtio: use generic name when possible
    
    We have two different virtio buses: pci and s390. The abstraction path
    taken in qemu is to have generic aliases for each device type in the
    architecture specific qdev devices.
    
    So let's make use of these aliases whenever we can and define them
    whenever we can.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/blockdev.c b/blockdev.c
index ecf2252..bbe92fe 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -503,7 +503,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     case IF_VIRTIO:
         /* add virtio block device */
         opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
-        qemu_opt_set(opts, "driver", "virtio-blk-pci");
+        qemu_opt_set(opts, "driver", "virtio-blk");
         qemu_opt_set(opts, "drive", dinfo->id);
         if (devaddr)
             qemu_opt_set(opts, "addr", devaddr);
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 784dc01..d44eff2 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -325,6 +325,7 @@ static const VirtIOBindings virtio_s390_bindings = {
 static VirtIOS390DeviceInfo s390_virtio_net = {
     .init = s390_virtio_net_init,
     .qdev.name = "virtio-net-s390",
+    .qdev.alias = "virtio-net",
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
         DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
@@ -340,6 +341,7 @@ static VirtIOS390DeviceInfo s390_virtio_net = {
 static VirtIOS390DeviceInfo s390_virtio_blk = {
     .init = s390_virtio_blk_init,
     .qdev.name = "virtio-blk-s390",
+    .qdev.alias = "virtio-blk",
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
         DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index df10703..555f23f 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -873,6 +873,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.reset = virtio_pci_reset,
     },{
         .qdev.name  = "virtio-net-pci",
+        .qdev.alias = "virtio-net",
         .qdev.size  = sizeof(VirtIOPCIProxy),
         .init       = virtio_net_init_pci,
         .exit       = virtio_net_exit_pci,
@@ -911,6 +912,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.reset = virtio_pci_reset,
     },{
         .qdev.name = "virtio-balloon-pci",
+        .qdev.alias = "virtio-balloon",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_balloon_init_pci,
         .exit      = virtio_exit_pci,
@@ -922,6 +924,7 @@ static PCIDeviceInfo virtio_info[] = {
     },{
 #ifdef CONFIG_VIRTFS
         .qdev.name = "virtio-9p-pci",
+        .qdev.alias = "virtio-9p",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_9p_init_pci,
         .qdev.props = (Property[]) {
diff --git a/vl.c b/vl.c
index 4d9e503..de232b7 100644
--- a/vl.c
+++ b/vl.c
@@ -1598,7 +1598,7 @@ static int balloon_parse(const char *arg)
             /* create empty opts */
             opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
         }
-        qemu_opt_set(opts, "driver", "virtio-balloon-pci");
+        qemu_opt_set(opts, "driver", "virtio-balloon");
         return 0;
     }
 
@@ -2484,12 +2484,12 @@ int main(int argc, char **argv, char **envp)
                          qemu_opt_get(opts, "path"),
                          qemu_opt_get(opts, "security_model"));
 
-                len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
+                len = strlen("virtio-9p,fsdev=,mount_tag=");
                 len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
                 arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
 
                 snprintf(arg_9p, (len + 1) * sizeof(*arg_9p),
-                         "virtio-9p-pci,fsdev=%s,mount_tag=%s",
+                         "virtio-9p,fsdev=%s,mount_tag=%s",
                          qemu_opt_get(opts, "mount_tag"),
                          qemu_opt_get(opts, "mount_tag"));
 
commit 1b01b4e717ada625575c207105b0b270c0b8467d
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Mar 29 15:29:28 2011 +0200

    Only build ivshmem when CONFIG_PCI && CONFIG_KVM
    
    The ivshmem depends on PCI and KVM, not only KVM. Reflect this
    in the Makefile, so we don't get build errors on s390x.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    CC: Cam Macdonell <cam at cs.ualberta.ca>
    CC: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile.target b/Makefile.target
index ddb0931..04e20dd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -209,7 +209,13 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
 
 # Inter-VM PCI shared memory
-obj-$(CONFIG_KVM) += ivshmem.o
+CONFIG_IVSHMEM =
+ifeq ($(CONFIG_KVM), y)
+  ifeq ($(CONFIG_PCI), y)
+    CONFIG_IVSHMEM = y
+  endif
+endif
+obj-$(CONFIG_IVSHMEM) += ivshmem.o
 
 # Hardware support
 obj-i386-y += vga.o
commit 6d65516f774c62a1abde3e52b689ac743b9ccc71
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 3 08:55:35 2011 +0200

    w32: Fix compilation (wrong include file)
    
    arpa/inet.h is not available for w32, so commit
    edbb21363fbfe40e050f583df921484cbc31c79d breaks
    w32 compilations.
    
    This is fixed by using qemu_socket.h.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 8506fed..28eb9d1 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -8,9 +8,8 @@
  * See the COPYING file in the top-level directory.
  */
 
-#include <arpa/inet.h>
-
 #include "qemu-char.h"
+#include "qemu_socket.h"
 #include "monitor.h"
 #include "hw/ccid.h"
 #include "libcacard/vscard_common.h"
commit 0ce235a7ee5a1852c0a18d4764ac0a6700805c83
Author: Gleb Natapov <gleb at redhat.com>
Date:   Thu Mar 31 11:27:23 2011 +0200

    register signal handler after initializing SDL.
    
    SDL library initialization mangles signal handlers, so QEMU should
    register them after initializing SDL. This was the case before and code
    even have a comment about that. Fix it to be so again.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/vl.c b/vl.c
index 5c80600..4d9e503 100644
--- a/vl.c
+++ b/vl.c
@@ -3059,9 +3059,6 @@ int main(int argc, char **argv, char **envp)
 
     cpu_synchronize_all_post_init();
 
-    /* must be after terminal init, SDL library changes signal handlers */
-    os_setup_signal_handling();
-
     set_numa_modes();
 
     current_machine = machine;
@@ -3117,6 +3114,9 @@ int main(int argc, char **argv, char **envp)
         break;
     }
 
+    /* must be after terminal init, SDL library changes signal handlers */
+    os_setup_signal_handling();
+
 #ifdef CONFIG_VNC
     /* init remote displays */
     if (vnc_display) {
commit f1d3fb04d55f46d39073e7089a5be43a16e80aa9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 30 22:03:38 2011 +0100

    vl.c: Tidy up message printed when we exit on a signal
    
    Tidy up the message printed when qemu exits due to a signal, so that
    it's clearer where the message is coming from and that it's not just
    stray debug output.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/vl.c b/vl.c
index d3d81e0..5c80600 100644
--- a/vl.c
+++ b/vl.c
@@ -1169,8 +1169,15 @@ int qemu_shutdown_requested(void)
 void qemu_kill_report(void)
 {
     if (shutdown_signal != -1) {
-        fprintf(stderr, "Got signal %d from pid %d\n",
-                         shutdown_signal, shutdown_pid);
+        fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal);
+        if (shutdown_pid == 0) {
+            /* This happens for eg ^C at the terminal, so it's worth
+             * avoiding printing an odd message in that case.
+             */
+            fputc('\n', stderr);
+        } else {
+            fprintf(stderr, " from pid %d\n", shutdown_pid);
+        }
         shutdown_signal = -1;
     }
 }
commit 22156ab498acf5f8104801148732ae8e83f336a0
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 28 22:00:30 2011 +0100

    net: Remove unused net-checksum.c file
    
    The common checksum functions were moved to net/checksum.c in commit
    7200ac3c7c8eefe574193b49eeff09f120e11ec7 but the original net-checksum.c
    was never deleted from the source tree.  Remove it now since all users
    of the checksum functions link against net/checksum.o and net-checksum.c
    is not even compiled anymore.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net-checksum.c b/net-checksum.c
deleted file mode 100644
index 4956c5c..0000000
--- a/net-checksum.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *  IP checksumming functions.
- *  (c) 2008 Gerd Hoffmann <kraxel at redhat.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; under version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw/hw.h"
-#include "net.h"
-
-#define PROTO_TCP  6
-#define PROTO_UDP 17
-
-uint32_t net_checksum_add(int len, uint8_t *buf)
-{
-    uint32_t sum = 0;
-    int i;
-
-    for (i = 0; i < len; i++) {
-	if (i & 1)
-	    sum += (uint32_t)buf[i];
-	else
-	    sum += (uint32_t)buf[i] << 8;
-    }
-    return sum;
-}
-
-uint16_t net_checksum_finish(uint32_t sum)
-{
-    while (sum>>16)
-	sum = (sum & 0xFFFF)+(sum >> 16);
-    return ~sum;
-}
-
-uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
-                             uint8_t *addrs, uint8_t *buf)
-{
-    uint32_t sum = 0;
-
-    sum += net_checksum_add(length, buf);         // payload
-    sum += net_checksum_add(8, addrs);            // src + dst address
-    sum += proto + length;                        // protocol & length
-    return net_checksum_finish(sum);
-}
-
-void net_checksum_calculate(uint8_t *data, int length)
-{
-    int hlen, plen, proto, csum_offset;
-    uint16_t csum;
-
-    if ((data[14] & 0xf0) != 0x40)
-	return; /* not IPv4 */
-    hlen  = (data[14] & 0x0f) * 4;
-    plen  = (data[16] << 8 | data[17]) - hlen;
-    proto = data[23];
-
-    switch (proto) {
-    case PROTO_TCP:
-	csum_offset = 16;
-	break;
-    case PROTO_UDP:
-	csum_offset = 6;
-	break;
-    default:
-	return;
-    }
-
-    if (plen < csum_offset+2)
-	return;
-
-    data[14+hlen+csum_offset]   = 0;
-    data[14+hlen+csum_offset+1] = 0;
-    csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen);
-    data[14+hlen+csum_offset]   = csum >> 8;
-    data[14+hlen+csum_offset+1] = csum & 0xff;
-}
commit d17161f6cc48a30b5e0c65a7d78ac47b069af06b
Author: Kevin Wolf <mail at kevin-wolf.de>
Date:   Sat Mar 26 19:37:56 2011 +0100

    e1000: Mask out lower bits of RDBAL/TDBAL
    
    Rx and Tx descriptors are 16 byte aligned, so the lower bits are
    ignored by real hardware. In fact, they always read back as zero on real
    hardware, but probably nobody relies on that.
    
    Signed-off-by: Kevin Wolf <mail at kevin-wolf.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/e1000.c b/hw/e1000.c
index 55daae0..fe3e812 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -517,6 +517,14 @@ txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp)
     return E1000_ICR_TXDW;
 }
 
+static uint64_t tx_desc_base(E1000State *s)
+{
+    uint64_t bah = s->mac_reg[TDBAH];
+    uint64_t bal = s->mac_reg[TDBAL] & ~0xf;
+
+    return (bah << 32) + bal;
+}
+
 static void
 start_xmit(E1000State *s)
 {
@@ -530,7 +538,7 @@ start_xmit(E1000State *s)
     }
 
     while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
-        base = ((uint64_t)s->mac_reg[TDBAH] << 32) + s->mac_reg[TDBAL] +
+        base = tx_desc_base(s) +
                sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
         cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
 
@@ -651,6 +659,14 @@ e1000_can_receive(VLANClientState *nc)
     return (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
 }
 
+static uint64_t rx_desc_base(E1000State *s)
+{
+    uint64_t bah = s->mac_reg[RDBAH];
+    uint64_t bal = s->mac_reg[RDBAL] & ~0xf;
+
+    return (bah << 32) + bal;
+}
+
 static ssize_t
 e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
@@ -700,8 +716,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         if (desc_size > s->rxbuf_size) {
             desc_size = s->rxbuf_size;
         }
-        base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +
-               sizeof(desc) * s->mac_reg[RDH];
+        base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH];
         cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
commit 425189a8ffc1247cc803bf6e1ffea42c47831684
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 22 11:02:09 2011 +0100

    gdbstub: Catch and report more vmstop reasons
    
    When the VM goes into stop state while there is a gdb frontend attached,
    it makes sense to inform gdb about this fact and at least a bit about
    the stop reason. Basically, all stops are interesting except for the
    temporary VMSTOP_SAVE/LOADVM.
    
    The patch maps the relevant VMSTOP reasons on unique and more or less
    associatable signals that gdb understands.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/gdbstub.c b/gdbstub.c
index 1e9f931..0838948 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -45,7 +45,12 @@
 enum {
     GDB_SIGNAL_0 = 0,
     GDB_SIGNAL_INT = 2,
+    GDB_SIGNAL_QUIT = 3,
     GDB_SIGNAL_TRAP = 5,
+    GDB_SIGNAL_ABRT = 6,
+    GDB_SIGNAL_ALRM = 14,
+    GDB_SIGNAL_IO = 23,
+    GDB_SIGNAL_XCPU = 24,
     GDB_SIGNAL_UNKNOWN = 143
 };
 
@@ -2270,14 +2275,11 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
     const char *type;
     int ret;
 
-    if (running || (reason != VMSTOP_DEBUG && reason != VMSTOP_USER) ||
-        s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
+    if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
         return;
     }
-    /* disable single step if it was enable */
-    cpu_single_step(env, 0);
-
-    if (reason == VMSTOP_DEBUG) {
+    switch (reason) {
+    case VMSTOP_DEBUG:
         if (env->watchpoint_hit) {
             switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
             case BP_MEM_READ:
@@ -2294,17 +2296,44 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
                      GDB_SIGNAL_TRAP, gdb_id(env), type,
                      env->watchpoint_hit->vaddr);
-            put_packet(s, buf);
             env->watchpoint_hit = NULL;
-            return;
+            goto send_packet;
         }
-	tb_flush(env);
+        tb_flush(env);
         ret = GDB_SIGNAL_TRAP;
-    } else {
+        break;
+    case VMSTOP_USER:
         ret = GDB_SIGNAL_INT;
+        break;
+    case VMSTOP_SHUTDOWN:
+        ret = GDB_SIGNAL_QUIT;
+        break;
+    case VMSTOP_DISKFULL:
+        ret = GDB_SIGNAL_IO;
+        break;
+    case VMSTOP_WATCHDOG:
+        ret = GDB_SIGNAL_ALRM;
+        break;
+    case VMSTOP_PANIC:
+        ret = GDB_SIGNAL_ABRT;
+        break;
+    case VMSTOP_SAVEVM:
+    case VMSTOP_LOADVM:
+        return;
+    case VMSTOP_MIGRATE:
+        ret = GDB_SIGNAL_XCPU;
+        break;
+    default:
+        ret = GDB_SIGNAL_UNKNOWN;
+        break;
     }
     snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env));
+
+send_packet:
     put_packet(s, buf);
+
+    /* disable single step if it was enabled */
+    cpu_single_step(env, 0);
 }
 #endif
 
commit 2917dce477f91e933052f5555b4c6be961ff624e
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 3 21:36:36 2011 +0200

    tests/cris: Fix some errors and potential crashes
    
    These errors were reported by cppcheck:
    
    tests/cris/check_openpf1.c:30: error:
    Mismatching allocation and deallocation: f
    
    tests/cris/check_openpf2.c:13: error:
    Mismatching allocation and deallocation: f
    
    tests/cris/check_stat3.c:16: error:
    Buffer overrun possible for long cmd-line args
    
    tests/cris/check_stat4.c:18: error:
    Buffer overrun possible for long cmd-line args
    
    The first two are obvious coding errors (fopen needs fclose, not close).
    
    The last two may seem less important (nobody will start test code
    with an argument of more than 1022 characters which raises a buffer
    overrun). Fixing them nevertheless helps with static code checks
    like those done by cppcheck.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/tests/cris/check_openpf1.c b/tests/cris/check_openpf1.c
index 1d71e0b..fdcf4c5 100644
--- a/tests/cris/check_openpf1.c
+++ b/tests/cris/check_openpf1.c
@@ -27,7 +27,7 @@ int main (int argc, char *argv[])
   f = fopen (fnam, "rb");
   if (f == NULL)
     abort ();
-  close (f);
+  fclose(f);
 
   /* Cover another execution path.  */
   if (fopen ("/nonexistent", "rb") != NULL
diff --git a/tests/cris/check_openpf2.c b/tests/cris/check_openpf2.c
index f44a8f3..5d56189 100644
--- a/tests/cris/check_openpf2.c
+++ b/tests/cris/check_openpf2.c
@@ -10,7 +10,7 @@ int main (int argc, char *argv[])
   FILE *f = fopen ("check_openpf2.c", "rb");
   if (f == NULL)
     abort ();
-  close (f);
+  fclose(f);
   printf ("pass\n");
   return 0;
 }
diff --git a/tests/cris/check_stat3.c b/tests/cris/check_stat3.c
index 3b5b217..36a9d5d 100644
--- a/tests/cris/check_stat3.c
+++ b/tests/cris/check_stat3.c
@@ -13,7 +13,7 @@ int main (int argc, char *argv[])
   char path[1024] = "/";
   struct stat buf;
 
-  strcat (path, argv[0]);
+  strncat(path, argv[0], sizeof(path) - 2);
   if (stat (".", &buf) != 0
       || !S_ISDIR (buf.st_mode))
     abort ();
diff --git a/tests/cris/check_stat4.c b/tests/cris/check_stat4.c
index e1955ca..04f21fe 100644
--- a/tests/cris/check_stat4.c
+++ b/tests/cris/check_stat4.c
@@ -15,7 +15,7 @@ int main (int argc, char *argv[])
   char path[1024] = "/";
   struct stat buf;
 
-  strcat (path, argv[0]);
+  strncat(path, argv[0], sizeof(path) - 2);
   if (lstat (".", &buf) != 0
       || !S_ISDIR (buf.st_mode))
     abort ();
commit 9bcfc7daabb138b0fe3d64d74892942d482e5bbd
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Wed Mar 16 18:05:01 2011 +0900

    ioapic: when switches to level trigger mode, interrupts raised repeatedly.
    
    - the trigger mode is edge at first
    - During initializatoin, the interrupt is raised as edge which is masked.
      The corresponding bit of irr is set.
    - Then the mode is switched to level and it's unmasked.
    - the bit of irr is set, so the interrupt is raised repeatedly by
      ioapic_service().
    - OS considers that the irq line is broken and falls back to polling mode.
    
    This patch fixes the issues.
    After raising edige, clear the bit of irr.
    
    > Bringing up interface eth0:
    > Determining IP information for eth0...irq 18: nobody cared (try booting with the "irqpoll" option)
    > Pid: 4126, comm: ip Not tainted 2.6.38-rc7 #1
    > Call Trace:
    >  <IRQ>  [<ffffffff8105b009>] ? __report_bad_irq+0x38/0x87
    >  [<ffffffff8105b177>] ? note_interrupt+0x11f/0x188
    >  [<ffffffff8105bacf>] ? handle_fasteoi_irq+0xa7/0xd1
    >  [<ffffffff810046ff>] ? handle_irq+0x83/0x8c
    >  [<ffffffff81003eb9>] ? do_IRQ+0x48/0xaf
    >  [<ffffffff81300513>] ? ret_from_intr+0x0/0xe
    >  [<ffffffff81031ab8>] ? __do_softirq+0x4f/0x114
    >  [<ffffffff81002d6c>] ? call_softirq+0x1c/0x28
    >  [<ffffffff81004647>] ? do_softirq+0x33/0x68
    >  [<ffffffff810316fb>] ? irq_exit+0x36/0x38
    >  [<ffffffff81015f2c>] ? smp_apic_timer_interrupt+0x88/0x96
    >  [<ffffffff81002853>] ? apic_timer_interrupt+0x13/0x20
    >  <EOI>  [<ffffffff810177ed>] ? __ioapic_set_affinity+0x68/0x7c
    >  [<ffffffff813000f0>] ? _raw_spin_unlock_irqrestore+0x8/0xa
    >  [<ffffffff8105a84f>] ? __setup_irq+0x224/0x2cb
    >  [<ffffffff8120e3c5>] ? e1000_intr+0x0/0x103
    >  [<ffffffff8105a9c7>] ? request_threaded_irq+0xd1/0x114
    >  [<ffffffff8120e396>] ? e1000_request_irq+0x34/0x63
    >  [<ffffffff8121237d>] ? e1000_open+0x81/0x11f
    >  [<ffffffff8129097c>] ? call_netdevice_notifiers+0x45/0x4a
    >  [<ffffffff81290d8d>] ? __dev_open+0x97/0xc4
    >  [<ffffffff8128e9c5>] ? __dev_change_flags+0xb9/0x13d
    >  [<ffffffff81290cc1>] ? dev_change_flags+0x1c/0x51
    >  [<ffffffff812d0542>] ? devinet_ioctl+0x26e/0x594
    >  [<ffffffff812d174c>] ? inet_ioctl+0x92/0xaa
    >  [<ffffffff81281d75>] ? T.1003+0x13/0x32
    >  [<ffffffff81282152>] ? sock_ioctl+0x1f2/0x1ff
    >  [<ffffffff810ae2d3>] ? do_vfs_ioctl+0x498/0x4e7
    >  [<ffffffff81281203>] ? sock_alloc_file+0xb3/0x115
    >  [<ffffffff8109f79f>] ? fd_install+0x31/0x5d
    >  [<ffffffff810ae364>] ? sys_ioctl+0x42/0x65
    >  [<ffffffff81001f3b>] ? system_call_fastpath+0x16/0x1b
    > handlers:
    > [<ffffffff8120e3c5>] (e1000_intr+0x0/0x103)
    > Disabling IRQ #18
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 569327d..8557e5c 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -164,6 +164,7 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
             if (level) {
                 s->irr |= mask;
                 ioapic_service(s);
+                s->irr &= ~mask;
             }
         }
     }
commit 4ff9786c67f7c7180f33ec146e9acc9ce90adfa9
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Mar 13 15:44:02 2011 +0100

    Fix trivial "endianness bugs"
    
    Replace endianess -> endianness.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index b74dcfa..a847aa9 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -139,36 +139,36 @@ static int aud_to_sdlfmt (audfmt_e fmt)
     }
 }
 
-static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
+static int sdl_to_audfmt(int sdlfmt, audfmt_e *fmt, int *endianness)
 {
     switch (sdlfmt) {
     case AUDIO_S8:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_S8;
         break;
 
     case AUDIO_U8:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_U8;
         break;
 
     case AUDIO_S16LSB:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_S16;
         break;
 
     case AUDIO_U16LSB:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_U16;
         break;
 
     case AUDIO_S16MSB:
-        *endianess = 1;
+        *endianness = 1;
         *fmt = AUD_FMT_S16;
         break;
 
     case AUDIO_U16MSB:
-        *endianess = 1;
+        *endianness = 1;
         *fmt = AUD_FMT_U16;
         break;
 
@@ -338,7 +338,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
     SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
     SDLAudioState *s = &glob_sdl;
     SDL_AudioSpec req, obt;
-    int endianess;
+    int endianness;
     int err;
     audfmt_e effective_fmt;
     struct audsettings obt_as;
@@ -354,7 +354,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
         return -1;
     }
 
-    err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess);
+    err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
     if (err) {
         sdl_close (s);
         return -1;
@@ -363,7 +363,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
     obt_as.freq = obt.freq;
     obt_as.nchannels = obt.channels;
     obt_as.fmt = effective_fmt;
-    obt_as.endianness = endianess;
+    obt_as.endianness = endianness;
 
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = obt.samples;
diff --git a/block/vdi.c b/block/vdi.c
index 9054079..701745b 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -113,7 +113,7 @@ void uuid_unparse(const uuid_t uu, char *out);
  */
 #define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
 
-/* Unallocated blocks use this index (no need to convert endianess). */
+/* Unallocated blocks use this index (no need to convert endianness). */
 #define VDI_UNALLOCATED UINT32_MAX
 
 #if !defined(CONFIG_UUID)
@@ -194,7 +194,7 @@ typedef struct {
     uint32_t block_sectors;
     /* First sector of block map. */
     uint32_t bmap_sector;
-    /* VDI header (converted to host endianess). */
+    /* VDI header (converted to host endianness). */
     VdiHeader header;
 } BDRVVdiState;
 
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index fdb2b40..b54b169 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -923,7 +923,7 @@ static void dec_load(DisasContext *dc)
     /*
      * When doing reverse accesses we need to do two things.
      *
-     * 1. Reverse the address wrt endianess.
+     * 1. Reverse the address wrt endianness.
      * 2. Byteswap the data lanes on the way back into the CPU core.
      */
     if (rev && size != 4) {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 2419aa9..0b98d10 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -63,7 +63,7 @@ union fpr_t {
     uint32_t w[2]; /* binary single fixed-point */
 };
 /* define FP_ENDIAN_IDX to access the same location
- * in the fpr_t union regardless of the host endianess
+ * in the fpr_t union regardless of the host endianness
  */
 #if defined(HOST_WORDS_BIGENDIAN)
 #  define FP_ENDIAN_IDX 1
diff --git a/usb-bsd.c b/usb-bsd.c
index abcb60c..50ccd48 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -464,7 +464,7 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
                 printf("usb_host_scan: couldn't get device information for %s - %s\n",
                        devbuf, strerror(errno));
 
-            // XXX: might need to fixup endianess of word values before copying over
+            /* XXX: might need to fixup endianness of word values before copying over */
 
             vendor_id = dev_info.udi_vendorNo;
             product_id = dev_info.udi_productNo;
commit 2055283bcc8292fd63c772ed90a2502f427b2174
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 7 11:10:32 2011 +0000

    hw/vexpress.c: Add model of ARM Versatile Express board
    
    Add a model of the ARM Versatile Express board (with A9MPx4
    daughterboard).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile.target b/Makefile.target
index ace5608..ddb0931 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -333,6 +333,7 @@ obj-arm-y += framebuffer.o
 obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
 obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
 obj-arm-y += syborg_virtio.o
+obj-arm-y += vexpress.o
 
 obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
diff --git a/hw/vexpress.c b/hw/vexpress.c
new file mode 100644
index 0000000..9ffd332
--- /dev/null
+++ b/hw/vexpress.c
@@ -0,0 +1,224 @@
+/*
+ * ARM Versatile Express emulation.
+ *
+ * Copyright (c) 2010 - 2011 B Labs Ltd.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Bahadir Balban, Amit Mahajan, Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+
+#define SMP_BOOT_ADDR 0xe0000000
+
+#define VEXPRESS_BOARD_ID 0x8e0
+
+static struct arm_boot_info vexpress_binfo = {
+    .smp_loader_start = SMP_BOOT_ADDR,
+};
+
+static void vexpress_a9_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    ram_addr_t ram_offset, vram_offset, sram_offset;
+    DeviceState *dev, *sysctl;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    int n;
+    qemu_irq cpu_irq[4];
+    uint32_t proc_id;
+    uint32_t sys_id;
+    ram_addr_t low_ram_size, vram_size, sram_size;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    if (ram_size > 0x40000000) {
+        /* 1GB is the maximum the address space permits */
+        fprintf(stderr, "vexpress: cannot model more than 1GB RAM\n");
+        exit(1);
+    }
+
+    ram_offset = qemu_ram_alloc(NULL, "vexpress.highmem", ram_size);
+    low_ram_size = ram_size;
+    if (low_ram_size > 0x4000000) {
+        low_ram_size = 0x4000000;
+    }
+    /* RAM is from 0x60000000 upwards. The bottom 64MB of the
+     * address space should in theory be remappable to various
+     * things including ROM or RAM; we always map the RAM there.
+     */
+    cpu_register_physical_memory(0x0, low_ram_size, ram_offset | IO_MEM_RAM);
+    cpu_register_physical_memory(0x60000000, ram_size,
+                                 ram_offset | IO_MEM_RAM);
+
+    /* 0x1e000000 A9MPCore (SCU) private memory region */
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    vexpress_binfo.smp_priv_base = 0x1e000000;
+    sysbus_mmio_map(busdev, 0, vexpress_binfo.smp_priv_base);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+    /* Interrupts [42:0] are from the motherboard;
+     * [47:43] are reserved; [63:48] are daughterboard
+     * peripherals. Note that some documentation numbers
+     * external interrupts starting from 32 (because the
+     * A9MP has internal interrupts 0..31).
+     */
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Motherboard peripherals CS7 : 0x10000000 .. 0x10020000 */
+    sys_id = 0x1190f500;
+    proc_id = 0x0c000191;
+
+    /* 0x10000000 System registers */
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_init_nofail(sysctl);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
+
+    /* 0x10001000 SP810 system control */
+    /* 0x10002000 serial bus PCI */
+    /* 0x10004000 PL041 audio */
+
+    dev = sysbus_create_varargs("pl181", 0x10005000, pic[9], pic[10], NULL);
+    /* Wire up MMC card detect and read-only signals */
+    qdev_connect_gpio_out(dev, 0,
+                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
+    qdev_connect_gpio_out(dev, 1,
+                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
+
+    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[12]);
+    sysbus_create_simple("pl050_mouse", 0x10007000, pic[13]);
+
+    sysbus_create_simple("pl011", 0x10009000, pic[5]);
+    sysbus_create_simple("pl011", 0x1000a000, pic[6]);
+    sysbus_create_simple("pl011", 0x1000b000, pic[7]);
+    sysbus_create_simple("pl011", 0x1000c000, pic[8]);
+
+    /* 0x1000f000 SP805 WDT */
+
+    sysbus_create_simple("sp804", 0x10011000, pic[2]);
+    sysbus_create_simple("sp804", 0x10012000, pic[3]);
+
+    /* 0x10016000 Serial Bus DVI */
+
+    sysbus_create_simple("pl031", 0x10017000, pic[4]); /* RTC */
+
+    /* 0x1001a000 Compact Flash */
+
+    /* 0x1001f000 PL111 CLCD (motherboard) */
+
+    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
+
+    /* 0x10020000 PL111 CLCD (daughterboard) */
+    sysbus_create_simple("pl110", 0x10020000, pic[44]);
+
+    /* 0x10060000 AXI RAM */
+    /* 0x100e0000 PL341 Dynamic Memory Controller */
+    /* 0x100e1000 PL354 Static Memory Controller */
+    /* 0x100e2000 System Configuration Controller */
+
+    sysbus_create_simple("sp804", 0x100e4000, pic[48]);
+    /* 0x100e5000 SP805 Watchdog module */
+    /* 0x100e6000 BP147 TrustZone Protection Controller */
+    /* 0x100e9000 PL301 'Fast' AXI matrix */
+    /* 0x100ea000 PL301 'Slow' AXI matrix */
+    /* 0x100ec000 TrustZone Address Space Controller */
+    /* 0x10200000 CoreSight debug APB */
+    /* 0x1e00a000 PL310 L2 Cache Controller */
+
+    /* CS0: NOR0 flash          : 0x40000000 .. 0x44000000 */
+    /* CS4: NOR1 flash          : 0x44000000 .. 0x48000000 */
+    /* CS2: SRAM                : 0x48000000 .. 0x4a000000 */
+    sram_size = 0x2000000;
+    sram_offset = qemu_ram_alloc(NULL, "vexpress.sram", sram_size);
+    cpu_register_physical_memory(0x48000000, sram_size,
+                                 sram_offset | IO_MEM_RAM);
+
+    /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */
+
+    /* 0x4c000000 Video RAM */
+    vram_size = 0x800000;
+    vram_offset = qemu_ram_alloc(NULL, "vexpress.vram", vram_size);
+    cpu_register_physical_memory(0x4c000000, vram_size,
+                                 vram_offset | IO_MEM_RAM);
+
+    /* 0x4e000000 LAN9118 Ethernet */
+    if (nd_table[0].vlan) {
+        lan9118_init(&nd_table[0], 0x4e000000, pic[15]);
+    }
+
+    /* 0x4f000000 ISP1761 USB */
+
+    /* ??? Hack to map an additional page of ram for the secondary CPU
+       startup code.  I guess this works on real hardware because the
+       BootROM happens to be in ROM/flash or in memory that isn't clobbered
+       until after Linux boots the secondary CPUs.  */
+    ram_offset = qemu_ram_alloc(NULL, "vexpress.hack", 0x1000);
+    cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
+                                 ram_offset | IO_MEM_RAM);
+
+    vexpress_binfo.ram_size = ram_size;
+    vexpress_binfo.kernel_filename = kernel_filename;
+    vexpress_binfo.kernel_cmdline = kernel_cmdline;
+    vexpress_binfo.initrd_filename = initrd_filename;
+    vexpress_binfo.nb_cpus = smp_cpus;
+    vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
+    vexpress_binfo.loader_start = 0x60000000;
+    arm_load_kernel(first_cpu, &vexpress_binfo);
+}
+
+
+static QEMUMachine vexpress_a9_machine = {
+    .name = "vexpress-a9",
+    .desc = "ARM Versatile Express for Cortex-A9",
+    .init = vexpress_a9_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+};
+
+static void vexpress_machine_init(void)
+{
+    qemu_register_machine(&vexpress_a9_machine);
+}
+
+machine_init(vexpress_machine_init);
commit 622465e1fa4c07d96fcb6e8cbe746b1e3f3ff65e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 14 07:23:11 2011 +0000

    target-arm/helper.c: For float-int conversion helpers pass ints as ints
    
    Correct the argument and return types for the float<->int conversion helper
    functions so that integer arguments and return values are declared as
    uint32_t/uint64_t, not float32/float64. This allows us to remove the
    hand-rolled functions which were doing bitwise copies between the types
    via unions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 78f3d39..6788a4c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2486,135 +2486,90 @@ DO_VFP_cmp(s, float32)
 DO_VFP_cmp(d, float64)
 #undef DO_VFP_cmp
 
-/* Helper routines to perform bitwise copies between float and int.  */
-static inline float32 vfp_itos(uint32_t i)
-{
-    union {
-        uint32_t i;
-        float32 s;
-    } v;
-
-    v.i = i;
-    return v.s;
-}
-
-static inline uint32_t vfp_stoi(float32 s)
-{
-    union {
-        uint32_t i;
-        float32 s;
-    } v;
-
-    v.s = s;
-    return v.i;
-}
-
-static inline float64 vfp_itod(uint64_t i)
-{
-    union {
-        uint64_t i;
-        float64 d;
-    } v;
-
-    v.i = i;
-    return v.d;
-}
-
-static inline uint64_t vfp_dtoi(float64 d)
-{
-    union {
-        uint64_t i;
-        float64 d;
-    } v;
-
-    v.d = d;
-    return v.i;
-}
-
 /* Integer to float conversion.  */
-float32 VFP_HELPER(uito, s)(float32 x, CPUState *env)
+float32 VFP_HELPER(uito, s)(uint32_t x, CPUState *env)
 {
-    return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
+    return uint32_to_float32(x, &env->vfp.fp_status);
 }
 
-float64 VFP_HELPER(uito, d)(float32 x, CPUState *env)
+float64 VFP_HELPER(uito, d)(uint32_t x, CPUState *env)
 {
-    return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
+    return uint32_to_float64(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(sito, s)(float32 x, CPUState *env)
+float32 VFP_HELPER(sito, s)(uint32_t x, CPUState *env)
 {
-    return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
+    return int32_to_float32(x, &env->vfp.fp_status);
 }
 
-float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
+float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env)
 {
-    return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
+    return int32_to_float64(x, &env->vfp.fp_status);
 }
 
 /* Float to integer conversion.  */
-float32 VFP_HELPER(toui, s)(float32 x, CPUState *env)
+uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status));
+    return float32_to_uint32(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(toui, d)(float64 x, CPUState *env)
+uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status));
+    return float64_to_uint32(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env)
+uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float32_to_int32(x, &env->vfp.fp_status));
+    return float32_to_int32(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env)
+uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float64_to_int32(x, &env->vfp.fp_status));
+    return float64_to_int32(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env)
+uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status));
+    return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env)
+uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status));
+    return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
+uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
 {
     if (float32_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status));
+    return float32_to_int32_round_to_zero(x, &env->vfp.fp_status);
 }
 
-float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
+uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
 {
     if (float64_is_any_nan(x)) {
-        return float32_zero;
+        return 0;
     }
-    return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status));
+    return float64_to_int32_round_to_zero(x, &env->vfp.fp_status);
 }
 
 /* floating point conversion */
@@ -2637,33 +2592,33 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
 }
 
 /* VFP3 fixed point conversion.  */
-#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
-ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
+#define VFP_CONV_FIX(name, p, fsz, itype, sign) \
+float##fsz VFP_HELPER(name##to, p)(uint##fsz##_t  x, uint32_t shift, \
+                                   CPUState *env) \
 { \
-    ftype tmp; \
-    tmp = sign##int32_to_##ftype ((itype##_t)vfp_##p##toi(x), \
-                                  &env->vfp.fp_status); \
-    return ftype##_scalbn(tmp, -(int)shift, &env->vfp.fp_status); \
+    float##fsz tmp; \
+    tmp = sign##int32_to_##float##fsz ((itype##_t)x, &env->vfp.fp_status); \
+    return float##fsz##_scalbn(tmp, -(int)shift, &env->vfp.fp_status); \
 } \
-ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
+uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \
+                                      CPUState *env) \
 { \
-    ftype tmp; \
-    if (ftype##_is_any_nan(x)) { \
-        return ftype##_zero; \
+    float##fsz tmp; \
+    if (float##fsz##_is_any_nan(x)) { \
+        return 0; \
     } \
-    tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
-    return vfp_ito##p(ftype##_to_##itype##_round_to_zero(tmp, \
-        &env->vfp.fp_status)); \
-}
-
-VFP_CONV_FIX(sh, d, float64, int16, )
-VFP_CONV_FIX(sl, d, float64, int32, )
-VFP_CONV_FIX(uh, d, float64, uint16, u)
-VFP_CONV_FIX(ul, d, float64, uint32, u)
-VFP_CONV_FIX(sh, s, float32, int16, )
-VFP_CONV_FIX(sl, s, float32, int32, )
-VFP_CONV_FIX(uh, s, float32, uint16, u)
-VFP_CONV_FIX(ul, s, float32, uint32, u)
+    tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \
+    return float##fsz##_to_##itype##_round_to_zero(tmp, &env->vfp.fp_status); \
+}
+
+VFP_CONV_FIX(sh, d, 64, int16, )
+VFP_CONV_FIX(sl, d, 64, int32, )
+VFP_CONV_FIX(uh, d, 64, uint16, u)
+VFP_CONV_FIX(ul, d, 64, uint32, u)
+VFP_CONV_FIX(sh, s, 32, int16, )
+VFP_CONV_FIX(sl, s, 32, int32, )
+VFP_CONV_FIX(uh, s, 32, uint16, u)
+VFP_CONV_FIX(ul, s, 32, uint32, u)
 #undef VFP_CONV_FIX
 
 /* Half precision conversions.  */
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index bd6977c..9de10e3 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -96,36 +96,36 @@ DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
 DEF_HELPER_2(vfp_fcvtds, f64, f32, env)
 DEF_HELPER_2(vfp_fcvtsd, f32, f64, env)
 
-DEF_HELPER_2(vfp_uitos, f32, f32, env)
-DEF_HELPER_2(vfp_uitod, f64, f32, env)
-DEF_HELPER_2(vfp_sitos, f32, f32, env)
-DEF_HELPER_2(vfp_sitod, f64, f32, env)
-
-DEF_HELPER_2(vfp_touis, f32, f32, env)
-DEF_HELPER_2(vfp_touid, f32, f64, env)
-DEF_HELPER_2(vfp_touizs, f32, f32, env)
-DEF_HELPER_2(vfp_touizd, f32, f64, env)
-DEF_HELPER_2(vfp_tosis, f32, f32, env)
-DEF_HELPER_2(vfp_tosid, f32, f64, env)
-DEF_HELPER_2(vfp_tosizs, f32, f32, env)
-DEF_HELPER_2(vfp_tosizd, f32, f64, env)
-
-DEF_HELPER_3(vfp_toshs, f32, f32, i32, env)
-DEF_HELPER_3(vfp_tosls, f32, f32, i32, env)
-DEF_HELPER_3(vfp_touhs, f32, f32, i32, env)
-DEF_HELPER_3(vfp_touls, f32, f32, i32, env)
-DEF_HELPER_3(vfp_toshd, f64, f64, i32, env)
-DEF_HELPER_3(vfp_tosld, f64, f64, i32, env)
-DEF_HELPER_3(vfp_touhd, f64, f64, i32, env)
-DEF_HELPER_3(vfp_tould, f64, f64, i32, env)
-DEF_HELPER_3(vfp_shtos, f32, f32, i32, env)
-DEF_HELPER_3(vfp_sltos, f32, f32, i32, env)
-DEF_HELPER_3(vfp_uhtos, f32, f32, i32, env)
-DEF_HELPER_3(vfp_ultos, f32, f32, i32, env)
-DEF_HELPER_3(vfp_shtod, f64, f64, i32, env)
-DEF_HELPER_3(vfp_sltod, f64, f64, i32, env)
-DEF_HELPER_3(vfp_uhtod, f64, f64, i32, env)
-DEF_HELPER_3(vfp_ultod, f64, f64, i32, env)
+DEF_HELPER_2(vfp_uitos, f32, i32, env)
+DEF_HELPER_2(vfp_uitod, f64, i32, env)
+DEF_HELPER_2(vfp_sitos, f32, i32, env)
+DEF_HELPER_2(vfp_sitod, f64, i32, env)
+
+DEF_HELPER_2(vfp_touis, i32, f32, env)
+DEF_HELPER_2(vfp_touid, i32, f64, env)
+DEF_HELPER_2(vfp_touizs, i32, f32, env)
+DEF_HELPER_2(vfp_touizd, i32, f64, env)
+DEF_HELPER_2(vfp_tosis, i32, f32, env)
+DEF_HELPER_2(vfp_tosid, i32, f64, env)
+DEF_HELPER_2(vfp_tosizs, i32, f32, env)
+DEF_HELPER_2(vfp_tosizd, i32, f64, env)
+
+DEF_HELPER_3(vfp_toshs, i32, f32, i32, env)
+DEF_HELPER_3(vfp_tosls, i32, f32, i32, env)
+DEF_HELPER_3(vfp_touhs, i32, f32, i32, env)
+DEF_HELPER_3(vfp_touls, i32, f32, i32, env)
+DEF_HELPER_3(vfp_toshd, i64, f64, i32, env)
+DEF_HELPER_3(vfp_tosld, i64, f64, i32, env)
+DEF_HELPER_3(vfp_touhd, i64, f64, i32, env)
+DEF_HELPER_3(vfp_tould, i64, f64, i32, env)
+DEF_HELPER_3(vfp_shtos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_sltos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_uhtos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_ultos, f32, i32, i32, env)
+DEF_HELPER_3(vfp_shtod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_sltod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_uhtod, f64, i64, i32, env)
+DEF_HELPER_3(vfp_ultod, f64, i64, i32, env)
 
 DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
commit 4a9f9cb24de52e93aae7539a004dd20314ca1c0c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:26 2011 +0000

    target-arm: Use new softfloat min/max functions for VMAX, VMIN
    
    Use the new softfloat min/max functions to implement the Neon VMAX
    and VMIN instructions. This allows us to get the right behaviour
    for NaN and negative zero.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index bf324c6..71f1a7e 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1773,16 +1773,12 @@ uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
 /* NEON Float helpers.  */
 uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = make_float32(a);
-    float32 f1 = make_float32(b);
-    return (float32_compare_quiet(f0, f1, NFS) == -1) ? a : b;
+    return float32_val(float32_min(make_float32(a), make_float32(b), NFS));
 }
 
 uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = make_float32(a);
-    float32 f1 = make_float32(b);
-    return (float32_compare_quiet(f0, f1, NFS) == 1) ? a : b;
+    return float32_val(float32_max(make_float32(a), make_float32(b), NFS));
 }
 
 uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b)
commit 274f1b041e0d550750cc6992092ad0197b2c5320
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:25 2011 +0000

    softfloat: Add float*_min() and float*_max() functions
    
    Add min and max operations to softfloat. This allows us to implement
    propagation of NaNs and handling of negative zero correctly (unlike
    the approach of having target helper routines return one of the operands
    based on the result of a comparison op).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 08e4ae0..03fb948 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6057,6 +6057,55 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
     return float128_compare_internal(a, b, 1 STATUS_VAR);
 }
 
+/* min() and max() functions. These can't be implemented as
+ * 'compare and pick one input' because that would mishandle
+ * NaNs and +0 vs -0.
+ */
+#define MINMAX(s, nan_exp)                                              \
+INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
+                                        int ismin STATUS_PARAM )        \
+{                                                                       \
+    flag aSign, bSign;                                                  \
+    uint ## s ## _t av, bv;                                             \
+    a = float ## s ## _squash_input_denormal(a STATUS_VAR);             \
+    b = float ## s ## _squash_input_denormal(b STATUS_VAR);             \
+    if (float ## s ## _is_any_nan(a) ||                                 \
+        float ## s ## _is_any_nan(b)) {                                 \
+        return propagateFloat ## s ## NaN(a, b STATUS_VAR);             \
+    }                                                                   \
+    aSign = extractFloat ## s ## Sign(a);                               \
+    bSign = extractFloat ## s ## Sign(b);                               \
+    av = float ## s ## _val(a);                                         \
+    bv = float ## s ## _val(b);                                         \
+    if (aSign != bSign) {                                               \
+        if (ismin) {                                                    \
+            return aSign ? a : b;                                       \
+        } else {                                                        \
+            return aSign ? b : a;                                       \
+        }                                                               \
+    } else {                                                            \
+        if (ismin) {                                                    \
+            return (aSign ^ (av < bv)) ? a : b;                         \
+        } else {                                                        \
+            return (aSign ^ (av < bv)) ? b : a;                         \
+        }                                                               \
+    }                                                                   \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _min(float ## s a, float ## s b STATUS_PARAM)  \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 1 STATUS_VAR);                   \
+}                                                                       \
+                                                                        \
+float ## s float ## s ## _max(float ## s a, float ## s b STATUS_PARAM)  \
+{                                                                       \
+    return float ## s ## _minmax(a, b, 0 STATUS_VAR);                   \
+}
+
+MINMAX(32, 0xff)
+MINMAX(64, 0x7ff)
+
+
 /* Multiply A by 2 raised to the power N.  */
 float32 float32_scalbn( float32 a, int n STATUS_PARAM )
 {
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 5d05fa5..90f4250 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -324,6 +324,8 @@ int float32_le_quiet( float32, float32 STATUS_PARAM );
 int float32_lt_quiet( float32, float32 STATUS_PARAM );
 int float32_compare( float32, float32 STATUS_PARAM );
 int float32_compare_quiet( float32, float32 STATUS_PARAM );
+float32 float32_min(float32, float32 STATUS_PARAM);
+float32 float32_max(float32, float32 STATUS_PARAM);
 int float32_is_quiet_nan( float32 );
 int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
@@ -436,6 +438,8 @@ int float64_le_quiet( float64, float64 STATUS_PARAM );
 int float64_lt_quiet( float64, float64 STATUS_PARAM );
 int float64_compare( float64, float64 STATUS_PARAM );
 int float64_compare_quiet( float64, float64 STATUS_PARAM );
+float64 float64_min(float64, float64 STATUS_PARAM);
+float64 float64_max(float64, float64 STATUS_PARAM);
 int float64_is_quiet_nan( float64 a );
 int float64_is_signaling_nan( float64 );
 float64 float64_maybe_silence_nan( float64 );
commit 79c18be7dfe660ab48f9f535e6cabd38c9f1d73b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:24 2011 +0000

    target-arm: Correct ABD's handling of negative zeroes
    
    Implement ABD by taking the absolute value of the difference
    of the operands (as the ARM ARM specifies) rather than by
    flipping the order of the operands to the subtract based
    on the results of a comparison. The latter approch gives
    the wrong answers for some edge cases like negative zero.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 9d54a75..bf324c6 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1789,9 +1789,7 @@ uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b)
 {
     float32 f0 = make_float32(a);
     float32 f1 = make_float32(b);
-    return float32_val((float32_compare_quiet(f0, f1, NFS) == 1)
-                    ? float32_sub(f0, f1, NFS)
-                    : float32_sub(f1, f0, NFS));
+    return float32_val(float32_abs(float32_sub(f0, f1, NFS)));
 }
 
 uint32_t HELPER(neon_add_f32)(uint32_t a, uint32_t b)
commit 0e3261098ff41c40ce3381b8ad7cff330458da3d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:23 2011 +0000

    target-arm: Fix VCLE.F32 #0, VCLT.F32 #0 NaN handling
    
    Implementing the floating-point versions of VCLE #0 and VCLT #0 by
    doing a GT comparison and inverting the result gives the wrong
    result if the input is a NaN. Implement as a GT comparison with the
    operands swapped instead.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 39512bc..33417e6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5677,25 +5677,31 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             gen_neon_rsb(size, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
-                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
+                        case 24: /* Float VCGT #0 */
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
-                            if (op == 27)
-                                tcg_gen_not_i32(tmp, tmp);
                             break;
-                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
+                        case 25: /* Float VCGE #0 */
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_cge_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
-                            if (op == 28)
-                                tcg_gen_not_i32(tmp, tmp);
                             break;
                         case 26: /* Float VCEQ #0 */
                             tmp2 = tcg_const_i32(0);
                             gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
                             tcg_temp_free(tmp2);
                             break;
+                        case 27: /* Float VCLE #0 */
+                            tmp2 = tcg_const_i32(0);
+                            gen_helper_neon_cge_f32(tmp, tmp2, tmp);
+                            tcg_temp_free(tmp2);
+                            break;
+                        case 28: /* Float VCLT #0 */
+                            tmp2 = tcg_const_i32(0);
+                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
+                            tcg_temp_free(tmp2);
+                            break;
                         case 30: /* Float VABS */
                             gen_vfp_abs(0);
                             break;
commit c7498daea76948128c1298d78fe9e7e618b5ff7c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:22 2011 +0000

    target-arm: Return right result for Neon comparison with NaNs
    
    Fix the helper functions implementing the Neon floating point comparison
    ops (VCGE, VCGT, VCEQ, VACGT, VACGE) to return the right answer when
    one of the values being compared is a NaN.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 2108664..9d54a75 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1810,32 +1810,40 @@ uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b)
 }
 
 /* Floating point comparisons produce an integer result.  */
-#define NEON_VOP_FCMP(name, cmp) \
+#define NEON_VOP_FCMP(name, ok) \
 uint32_t HELPER(neon_##name)(uint32_t a, uint32_t b) \
 { \
-    if (float32_compare_quiet(make_float32(a), make_float32(b), NFS) cmp 0) { \
-        return ~0; \
-    } else { \
-        return 0; \
+    switch (float32_compare_quiet(make_float32(a), make_float32(b), NFS)) { \
+    ok return ~0; \
+    default: return 0; \
     } \
 }
 
-NEON_VOP_FCMP(ceq_f32, ==)
-NEON_VOP_FCMP(cge_f32, >=)
-NEON_VOP_FCMP(cgt_f32, >)
+NEON_VOP_FCMP(ceq_f32, case float_relation_equal:)
+NEON_VOP_FCMP(cge_f32, case float_relation_equal: case float_relation_greater:)
+NEON_VOP_FCMP(cgt_f32, case float_relation_greater:)
 
 uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b)
 {
     float32 f0 = float32_abs(make_float32(a));
     float32 f1 = float32_abs(make_float32(b));
-    return (float32_compare_quiet(f0, f1,NFS) >= 0) ? ~0 : 0;
+    switch (float32_compare_quiet(f0, f1, NFS)) {
+    case float_relation_equal:
+    case float_relation_greater:
+        return ~0;
+    default:
+        return 0;
+    }
 }
 
 uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
 {
     float32 f0 = float32_abs(make_float32(a));
     float32 f1 = float32_abs(make_float32(b));
-    return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0;
+    if (float32_compare_quiet(f0, f1, NFS) == float_relation_greater) {
+        return ~0;
+    }
+    return 0;
 }
 
 #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
commit 51d852672cb8536c541ed5b1dc4ee8f989a96cd7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 08:12:21 2011 +0000

    target-arm/neon_helper.c: Use make_float32/float32_val macros
    
    Use the softfloat make_float32 and float32_val macros to convert between
    softfloat's float32 type and raw uint32_t types, rather than private
    conversion functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 002a9c1..2108664 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -21,29 +21,6 @@
 static float_status neon_float_status;
 #define NFS &neon_float_status
 
-/* Helper routines to perform bitwise copies between float and int.  */
-static inline float32 vfp_itos(uint32_t i)
-{
-    union {
-        uint32_t i;
-        float32 s;
-    } v;
-
-    v.i = i;
-    return v.s;
-}
-
-static inline uint32_t vfp_stoi(float32 s)
-{
-    union {
-        uint32_t i;
-        float32 s;
-    } v;
-
-    v.s = s;
-    return v.i;
-}
-
 #define NEON_TYPE1(name, type) \
 typedef struct \
 { \
@@ -1796,50 +1773,51 @@ uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
 /* NEON Float helpers.  */
 uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = vfp_itos(a);
-    float32 f1 = vfp_itos(b);
+    float32 f0 = make_float32(a);
+    float32 f1 = make_float32(b);
     return (float32_compare_quiet(f0, f1, NFS) == -1) ? a : b;
 }
 
 uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = vfp_itos(a);
-    float32 f1 = vfp_itos(b);
+    float32 f0 = make_float32(a);
+    float32 f1 = make_float32(b);
     return (float32_compare_quiet(f0, f1, NFS) == 1) ? a : b;
 }
 
 uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = vfp_itos(a);
-    float32 f1 = vfp_itos(b);
-    return vfp_stoi((float32_compare_quiet(f0, f1, NFS) == 1)
+    float32 f0 = make_float32(a);
+    float32 f1 = make_float32(b);
+    return float32_val((float32_compare_quiet(f0, f1, NFS) == 1)
                     ? float32_sub(f0, f1, NFS)
                     : float32_sub(f1, f0, NFS));
 }
 
 uint32_t HELPER(neon_add_f32)(uint32_t a, uint32_t b)
 {
-    return vfp_stoi(float32_add(vfp_itos(a), vfp_itos(b), NFS));
+    return float32_val(float32_add(make_float32(a), make_float32(b), NFS));
 }
 
 uint32_t HELPER(neon_sub_f32)(uint32_t a, uint32_t b)
 {
-    return vfp_stoi(float32_sub(vfp_itos(a), vfp_itos(b), NFS));
+    return float32_val(float32_sub(make_float32(a), make_float32(b), NFS));
 }
 
 uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b)
 {
-    return vfp_stoi(float32_mul(vfp_itos(a), vfp_itos(b), NFS));
+    return float32_val(float32_mul(make_float32(a), make_float32(b), NFS));
 }
 
 /* Floating point comparisons produce an integer result.  */
 #define NEON_VOP_FCMP(name, cmp) \
 uint32_t HELPER(neon_##name)(uint32_t a, uint32_t b) \
 { \
-    if (float32_compare_quiet(vfp_itos(a), vfp_itos(b), NFS) cmp 0) \
+    if (float32_compare_quiet(make_float32(a), make_float32(b), NFS) cmp 0) { \
         return ~0; \
-    else \
+    } else { \
         return 0; \
+    } \
 }
 
 NEON_VOP_FCMP(ceq_f32, ==)
@@ -1848,15 +1826,15 @@ NEON_VOP_FCMP(cgt_f32, >)
 
 uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = float32_abs(vfp_itos(a));
-    float32 f1 = float32_abs(vfp_itos(b));
+    float32 f0 = float32_abs(make_float32(a));
+    float32 f1 = float32_abs(make_float32(b));
     return (float32_compare_quiet(f0, f1,NFS) >= 0) ? ~0 : 0;
 }
 
 uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
 {
-    float32 f0 = float32_abs(vfp_itos(a));
-    float32 f1 = float32_abs(vfp_itos(b));
+    float32 f0 = float32_abs(make_float32(a));
+    float32 f1 = float32_abs(make_float32(b));
     return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0;
 }
 
commit 1056c02b7b1a3daa3765a6b599800a453ee96c5f
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Dec 12 18:13:34 2010 +0200

    ccid: add docs
    
    Add documentation for the usb-ccid device and accompanying two card
    devices, ccid-card-emulated and ccid-card-passthru.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>

diff --git a/docs/ccid.txt b/docs/ccid.txt
new file mode 100644
index 0000000..b8e504a
--- /dev/null
+++ b/docs/ccid.txt
@@ -0,0 +1,135 @@
+Qemu CCID Device Documentation.
+
+Contents
+1. USB CCID device
+2. Building
+3. Using ccid-card-emulated with hardware
+4. Using ccid-card-emulated with certificates
+5. Using ccid-card-passthru with client side hardware
+6. Using ccid-card-passthru with client side certificates
+7. Passthrough protocol scenario
+8. libcacard
+
+1. USB CCID device
+
+The USB CCID device is a USB device implementing the CCID specification, which
+lets one connect smart card readers that implement the same spec. For more
+information see the specification:
+
+ Universal Serial Bus
+ Device Class: Smart Card
+ CCID
+ Specification for
+ Integrated Circuit(s) Cards Interface Devices
+ Revision 1.1
+ April 22rd, 2005
+
+Smartcard are used for authentication, single sign on, decryption in
+public/private schemes and digital signatures. A smartcard reader on the client
+cannot be used on a guest with simple usb passthrough since it will then not be
+available on the client, possibly locking the computer when it is "removed". On
+the other hand this device can let you use the smartcard on both the client and
+the guest machine. It is also possible to have a completely virtual smart card
+reader and smart card (i.e. not backed by a physical device) using this device.
+
+2. Building
+
+The cryptographic functions and access to the physical card is done via NSS.
+
+Installing NSS:
+
+In redhat/fedora:
+    yum install nss-devel
+In ubuntu/debian:
+    apt-get install libnss3-dev
+    (not tested on ubuntu)
+
+Configuring and building:
+    ./configure --enable-smartcard && make
+
+3. Using ccid-card-emulated with hardware
+
+Assuming you have a working smartcard on the host with the current
+user, using NSS, qemu acts as another NSS client using ccid-card-emulated:
+
+    qemu -usb -device usb-ccid -device ccid-card-emualated
+
+4. Using ccid-card-emulated with certificates
+
+You must create the certificates. This is a one time process. We use NSS
+certificates:
+
+    certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=cert1" -n cert1
+
+Note: you must have exactly three certificates.
+
+Assuming the current user can access the certificates (use certutil -L to
+verify), you can use the emulated card type with the certificates backend:
+
+    qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
+
+5. Using ccid-card-passthru with client side hardware
+
+on the host specify the ccid-card-passthru device with a suitable chardev:
+
+    qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
+
+on the client run vscclient, built when you built the libcacard library:
+    libcacard/vscclient <qemu-host> 2001
+
+6. Using ccid-card-passthru with client side certificates
+
+Run qemu as per #5, and run vscclient as follows:
+(Note: vscclient command line interface is in a state of change)
+
+    libcacard/vscclient -e "db=\"/etc/pki/nssdb\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)" <qemu-host> 2001
+
+7. Passthrough protocol scenario
+
+This is a typical interchange of messages when using the passthru card device.
+usb-ccid is a usb device. It defaults to an unattached usb device on startup.
+usb-ccid expects a chardev and expects the protocol defined in
+cac_card/vscard_common.h to be passed over that.
+The usb-ccid device can be in one of three modes:
+ * detached
+ * attached with no card
+ * attached with card
+
+A typical interchange is: (the arrow shows who started each exchange, it can be client
+originated or guest originated)
+
+client event      |      vscclient           |    passthru    |     usb-ccid  |  guest event
+----------------------------------------------------------------------------------------------
+                  |      VSC_Init            |                |               |
+                  |      VSC_ReaderAdd       |                |     attach    |
+                  |                          |                |               |  sees new usb device.
+card inserted ->  |                          |                |               |
+                  |      VSC_ATR             |   insert       |     insert    |  see new card
+                  |                          |                |               |
+                  |      VSC_APDU            |   VSC_APDU     |               | <- guest sends APDU
+client<->physical |                          |                |               |
+card APDU exchange|                          |                |               |
+client response ->|      VSC_APDU            |   VSC_APDU     |               |  receive APDU response
+                                                    ...
+                                    [APDU<->APDU repeats several times]
+                                                    ...
+card removed  ->  |                          |                |               |
+                  |      VSC_CardRemove      |   remove       |    remove     |   card removed
+                                                    ...
+                                    [(card insert, apdu's, card remove) repeat]
+                                                    ...
+kill/quit         |                          |                |               |
+  vscclient       |                          |                |               |
+                  |      VSC_ReaderRemove    |                |    detach     |
+                  |                          |                |               |   usb device removed.
+
+
+8. libcacard
+
+ccid-card-passthru and vscclient use libcacard as the card emulator.
+libcacard implements a completely virtual CAC (DoD standard for smart cards)
+compliant card and uses NSS to actually retrive certificates and do any
+encryption using the backend (real reader + card or file backed certificates).
+
+For documentation of cac_card see README in libcacard subdirectory.
+
commit 585738a6e62eb586f24782dee34306e7c375f9ba
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Oct 24 12:09:18 2010 +0200

    ccid: add ccid-card-emulated device
    
    This devices uses libcacard (internal) to emulate a smartcard conforming
    to the CAC standard. It attaches to the usb-ccid bus. Usage instructions
    (example command lines) are in the following patch in docs/ccid.txt. It
    uses libcacard which uses nss, so it can work with both hw cards and
    certificates (files).
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    ---
    
    changes from v20->v21: (Jes Sorenson review)
     * cosmetics
     * use qemu-thread and qemu_malloc/qemu_free
    
    changes from v19->v20:
     * checkpatch.pl
    
    changes from v18->v19:
     * add qdev.desc
     * backend: drop the enumeration property, back to using a string one.
    
    changes from v16->v17:
     * use PROP_TYPE_ENUM for backend
    
    changes from v15->v16:
     * fix error reporting in initfn
     * bump copyright year
     * update copyright license
    
    changes from v1:
     * remove stale comments, use only c-style comments
     * bugfix, forgot to set recv_len
     * change reader name to 'Virtual Reader'

diff --git a/Makefile.objs b/Makefile.objs
index 8c42524..c05f5e5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -201,6 +201,7 @@ hw-obj-$(CONFIG_DMA) += dma.o
 hw-obj-$(CONFIG_HPET) += hpet.o
 hw-obj-$(CONFIG_APPLESMC) += applesmc.o
 hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
+hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
new file mode 100644
index 0000000..0b07184
--- /dev/null
+++ b/hw/ccid-card-emulated.c
@@ -0,0 +1,595 @@
+/*
+ * CCID Card Device. Emulated card.
+ *
+ * Copyright (c) 2011 Red Hat.
+ * Written by Alon Levy.
+ *
+ * This code is licenced under the GNU LGPL, version 2 or later.
+ */
+
+/*
+ * It can be used to provide access to the local hardware in a non exclusive
+ * way, or it can use certificates. It requires the usb-ccid bus.
+ *
+ * Usage 1: standard, mirror hardware reader+card:
+ * qemu .. -usb -device usb-ccid -device ccid-card-emulated
+ *
+ * Usage 2: use certificates, no hardware required
+ * one time: create the certificates:
+ *  for i in 1 2 3; do
+ *      certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=user$i" -n user$i
+ *  done
+ * qemu .. -usb -device usb-ccid \
+ *  -device ccid-card-emulated,cert1=user1,cert2=user2,cert3=user3
+ *
+ * If you use a non default db for the certificates you can specify it using
+ * the db parameter.
+ */
+
+#include <eventt.h>
+#include <vevent.h>
+#include <vreader.h>
+#include <vcard_emul.h>
+
+#include "qemu-thread.h"
+#include "qemu-char.h"
+#include "monitor.h"
+#include "hw/ccid.h"
+
+#define DPRINTF(card, lvl, fmt, ...) \
+do {\
+    if (lvl <= card->debug) {\
+        printf("ccid-card-emul: %s: " fmt , __func__, ## __VA_ARGS__);\
+    } \
+} while (0)
+
+#define EMULATED_DEV_NAME "ccid-card-emulated"
+
+#define BACKEND_NSS_EMULATED_NAME "nss-emulated"
+#define BACKEND_CERTIFICATES_NAME "certificates"
+
+enum {
+    BACKEND_NSS_EMULATED = 1,
+    BACKEND_CERTIFICATES
+};
+
+#define DEFAULT_BACKEND BACKEND_NSS_EMULATED
+
+typedef struct EmulatedState EmulatedState;
+
+enum {
+    EMUL_READER_INSERT = 0,
+    EMUL_READER_REMOVE,
+    EMUL_CARD_INSERT,
+    EMUL_CARD_REMOVE,
+    EMUL_GUEST_APDU,
+    EMUL_RESPONSE_APDU,
+    EMUL_ERROR,
+};
+
+static const char *emul_event_to_string(uint32_t emul_event)
+{
+    switch (emul_event) {
+    case EMUL_READER_INSERT:
+        return "EMUL_READER_INSERT";
+    case EMUL_READER_REMOVE:
+        return "EMUL_READER_REMOVE";
+    case EMUL_CARD_INSERT:
+        return "EMUL_CARD_INSERT";
+    case EMUL_CARD_REMOVE:
+        return "EMUL_CARD_REMOVE";
+    case EMUL_GUEST_APDU:
+        return "EMUL_GUEST_APDU";
+    case EMUL_RESPONSE_APDU:
+        return "EMUL_RESPONSE_APDU";
+    case EMUL_ERROR:
+        return "EMUL_ERROR";
+    }
+    return "UNKNOWN";
+}
+
+typedef struct EmulEvent {
+    QSIMPLEQ_ENTRY(EmulEvent) entry;
+    union {
+        struct {
+            uint32_t type;
+        } gen;
+        struct {
+            uint32_t type;
+            uint64_t code;
+        } error;
+        struct {
+            uint32_t type;
+            uint32_t len;
+            uint8_t data[];
+        } data;
+    } p;
+} EmulEvent;
+
+#define MAX_ATR_SIZE 40
+struct EmulatedState {
+    CCIDCardState base;
+    uint8_t  debug;
+    char    *backend_str;
+    uint32_t backend;
+    char    *cert1;
+    char    *cert2;
+    char    *cert3;
+    char    *db;
+    uint8_t  atr[MAX_ATR_SIZE];
+    uint8_t  atr_length;
+    QSIMPLEQ_HEAD(event_list, EmulEvent) event_list;
+    QemuMutex event_list_mutex;
+    VReader *reader;
+    QSIMPLEQ_HEAD(guest_apdu_list, EmulEvent) guest_apdu_list;
+    QemuMutex vreader_mutex; /* and guest_apdu_list mutex */
+    QemuMutex handle_apdu_mutex;
+    QemuCond handle_apdu_cond;
+    int      pipe[2];
+    int      quit_apdu_thread;
+    QemuMutex apdu_thread_quit_mutex;
+    QemuCond apdu_thread_quit_cond;
+};
+
+static void emulated_apdu_from_guest(CCIDCardState *base,
+    const uint8_t *apdu, uint32_t len)
+{
+    EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
+    EmulEvent *event = (EmulEvent *)qemu_malloc(sizeof(EmulEvent) + len);
+
+    assert(event);
+    event->p.data.type = EMUL_GUEST_APDU;
+    event->p.data.len = len;
+    memcpy(event->p.data.data, apdu, len);
+    qemu_mutex_lock(&card->vreader_mutex);
+    QSIMPLEQ_INSERT_TAIL(&card->guest_apdu_list, event, entry);
+    qemu_mutex_unlock(&card->vreader_mutex);
+    qemu_mutex_lock(&card->handle_apdu_mutex);
+    qemu_cond_signal(&card->handle_apdu_cond);
+    qemu_mutex_unlock(&card->handle_apdu_mutex);
+}
+
+static const uint8_t *emulated_get_atr(CCIDCardState *base, uint32_t *len)
+{
+    EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
+
+    *len = card->atr_length;
+    return card->atr;
+}
+
+static void emulated_push_event(EmulatedState *card, EmulEvent *event)
+{
+    qemu_mutex_lock(&card->event_list_mutex);
+    QSIMPLEQ_INSERT_TAIL(&(card->event_list), event, entry);
+    qemu_mutex_unlock(&card->event_list_mutex);
+    if (write(card->pipe[1], card, 1) != 1) {
+        DPRINTF(card, 1, "write to pipe failed\n");
+    }
+}
+
+static void emulated_push_type(EmulatedState *card, uint32_t type)
+{
+    EmulEvent *event = (EmulEvent *)qemu_malloc(sizeof(EmulEvent));
+
+    assert(event);
+    event->p.gen.type = type;
+    emulated_push_event(card, event);
+}
+
+static void emulated_push_error(EmulatedState *card, uint64_t code)
+{
+    EmulEvent *event = (EmulEvent *)qemu_malloc(sizeof(EmulEvent));
+
+    assert(event);
+    event->p.error.type = EMUL_ERROR;
+    event->p.error.code = code;
+    emulated_push_event(card, event);
+}
+
+static void emulated_push_data_type(EmulatedState *card, uint32_t type,
+    const uint8_t *data, uint32_t len)
+{
+    EmulEvent *event = (EmulEvent *)qemu_malloc(sizeof(EmulEvent) + len);
+
+    assert(event);
+    event->p.data.type = type;
+    event->p.data.len = len;
+    memcpy(event->p.data.data, data, len);
+    emulated_push_event(card, event);
+}
+
+static void emulated_push_reader_insert(EmulatedState *card)
+{
+    emulated_push_type(card, EMUL_READER_INSERT);
+}
+
+static void emulated_push_reader_remove(EmulatedState *card)
+{
+    emulated_push_type(card, EMUL_READER_REMOVE);
+}
+
+static void emulated_push_card_insert(EmulatedState *card,
+    const uint8_t *atr, uint32_t len)
+{
+    emulated_push_data_type(card, EMUL_CARD_INSERT, atr, len);
+}
+
+static void emulated_push_card_remove(EmulatedState *card)
+{
+    emulated_push_type(card, EMUL_CARD_REMOVE);
+}
+
+static void emulated_push_response_apdu(EmulatedState *card,
+    const uint8_t *apdu, uint32_t len)
+{
+    emulated_push_data_type(card, EMUL_RESPONSE_APDU, apdu, len);
+}
+
+#define APDU_BUF_SIZE 270
+static void *handle_apdu_thread(void* arg)
+{
+    EmulatedState *card = arg;
+    uint8_t recv_data[APDU_BUF_SIZE];
+    int recv_len;
+    VReaderStatus reader_status;
+    EmulEvent *event;
+
+    while (1) {
+        qemu_mutex_lock(&card->handle_apdu_mutex);
+        qemu_cond_wait(&card->handle_apdu_cond, &card->handle_apdu_mutex);
+        qemu_mutex_unlock(&card->handle_apdu_mutex);
+        if (card->quit_apdu_thread) {
+            card->quit_apdu_thread = 0; /* debugging */
+            break;
+        }
+        qemu_mutex_lock(&card->vreader_mutex);
+        while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) {
+            event = QSIMPLEQ_FIRST(&card->guest_apdu_list);
+            assert((unsigned long)event > 1000);
+            QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry);
+            if (event->p.data.type != EMUL_GUEST_APDU) {
+                DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n");
+                qemu_free(event);
+                continue;
+            }
+            if (card->reader == NULL) {
+                DPRINTF(card, 1, "reader is NULL\n");
+                qemu_free(event);
+                continue;
+            }
+            recv_len = sizeof(recv_data);
+            reader_status = vreader_xfr_bytes(card->reader,
+                    event->p.data.data, event->p.data.len,
+                    recv_data, &recv_len);
+            DPRINTF(card, 2, "got back apdu of length %d\n", recv_len);
+            if (reader_status == VREADER_OK) {
+                emulated_push_response_apdu(card, recv_data, recv_len);
+            } else {
+                emulated_push_error(card, reader_status);
+            }
+            qemu_free(event);
+        }
+        qemu_mutex_unlock(&card->vreader_mutex);
+    }
+    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
+    qemu_cond_signal(&card->apdu_thread_quit_cond);
+    qemu_mutex_unlock(&card->apdu_thread_quit_mutex);
+    return NULL;
+}
+
+static void *event_thread(void *arg)
+{
+    int atr_len = MAX_ATR_SIZE;
+    uint8_t atr[MAX_ATR_SIZE];
+    VEvent *event = NULL;
+    EmulatedState *card = arg;
+
+    while (1) {
+        const char *reader_name;
+
+        event = vevent_wait_next_vevent();
+        if (event == NULL || event->type == VEVENT_LAST) {
+            break;
+        }
+        if (event->type != VEVENT_READER_INSERT) {
+            if (card->reader == NULL && event->reader != NULL) {
+                /* Happens after device_add followed by card remove or insert.
+                 * XXX: create synthetic add_reader events if vcard_emul_init
+                 * already called, which happens if device_del and device_add
+                 * are called */
+                card->reader = vreader_reference(event->reader);
+            } else {
+                if (event->reader != card->reader) {
+                    fprintf(stderr,
+                        "ERROR: wrong reader: quiting event_thread\n");
+                    break;
+                }
+            }
+        }
+        switch (event->type) {
+        case VEVENT_READER_INSERT:
+            /* TODO: take a specific reader. i.e. track which reader
+             * we are seeing here, check it is the one we want (the first,
+             * or by a particular name), and ignore if we don't want it.
+             */
+            reader_name = vreader_get_name(event->reader);
+            if (card->reader != NULL) {
+                DPRINTF(card, 2, "READER INSERT - replacing %s with %s\n",
+                    vreader_get_name(card->reader), reader_name);
+                qemu_mutex_lock(&card->vreader_mutex);
+                vreader_free(card->reader);
+                qemu_mutex_unlock(&card->vreader_mutex);
+                emulated_push_reader_remove(card);
+            }
+            qemu_mutex_lock(&card->vreader_mutex);
+            DPRINTF(card, 2, "READER INSERT %s\n", reader_name);
+            card->reader = vreader_reference(event->reader);
+            qemu_mutex_unlock(&card->vreader_mutex);
+            emulated_push_reader_insert(card);
+            break;
+        case VEVENT_READER_REMOVE:
+            DPRINTF(card, 2, " READER REMOVE: %s\n",
+                    vreader_get_name(event->reader));
+            qemu_mutex_lock(&card->vreader_mutex);
+            vreader_free(card->reader);
+            card->reader = NULL;
+            qemu_mutex_unlock(&card->vreader_mutex);
+            emulated_push_reader_remove(card);
+            break;
+        case VEVENT_CARD_INSERT:
+            /* get the ATR (intended as a response to a power on from the
+             * reader */
+            atr_len = MAX_ATR_SIZE;
+            vreader_power_on(event->reader, atr, &atr_len);
+            card->atr_length = (uint8_t)atr_len;
+            DPRINTF(card, 2, " CARD INSERT\n");
+            emulated_push_card_insert(card, atr, atr_len);
+            break;
+        case VEVENT_CARD_REMOVE:
+            DPRINTF(card, 2, " CARD REMOVE\n");
+            emulated_push_card_remove(card);
+            break;
+        case VEVENT_LAST: /* quit */
+            vevent_delete(event);
+            return NULL;
+            break;
+        default:
+            break;
+        }
+        vevent_delete(event);
+    }
+    return NULL;
+}
+
+static void pipe_read(void *opaque)
+{
+    EmulatedState *card = opaque;
+    EmulEvent *event, *next;
+    char dummy;
+    int len;
+
+    do {
+        len = read(card->pipe[0], &dummy, sizeof(dummy));
+    } while (len == sizeof(dummy));
+    qemu_mutex_lock(&card->event_list_mutex);
+    QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) {
+        DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type));
+        switch (event->p.gen.type) {
+        case EMUL_RESPONSE_APDU:
+            ccid_card_send_apdu_to_guest(&card->base, event->p.data.data,
+                event->p.data.len);
+            break;
+        case EMUL_READER_INSERT:
+            ccid_card_ccid_attach(&card->base);
+            break;
+        case EMUL_READER_REMOVE:
+            ccid_card_ccid_detach(&card->base);
+            break;
+        case EMUL_CARD_INSERT:
+            assert(event->p.data.len <= MAX_ATR_SIZE);
+            card->atr_length = event->p.data.len;
+            memcpy(card->atr, event->p.data.data, card->atr_length);
+            ccid_card_card_inserted(&card->base);
+            break;
+        case EMUL_CARD_REMOVE:
+            ccid_card_card_removed(&card->base);
+            break;
+        case EMUL_ERROR:
+            ccid_card_card_error(&card->base, event->p.error.code);
+            break;
+        default:
+            DPRINTF(card, 2, "unexpected event\n");
+            break;
+        }
+        qemu_free(event);
+    }
+    QSIMPLEQ_INIT(&card->event_list);
+    qemu_mutex_unlock(&card->event_list_mutex);
+}
+
+static int init_pipe_signaling(EmulatedState *card)
+{
+    if (pipe(card->pipe) < 0) {
+        DPRINTF(card, 2, "pipe creation failed\n");
+        return -1;
+    }
+    fcntl(card->pipe[0], F_SETFL, O_NONBLOCK);
+    fcntl(card->pipe[1], F_SETFL, O_NONBLOCK);
+    fcntl(card->pipe[0], F_SETOWN, getpid());
+    qemu_set_fd_handler(card->pipe[0], pipe_read, NULL, card);
+    return 0;
+}
+
+#define CERTIFICATES_DEFAULT_DB "/etc/pki/nssdb"
+#define CERTIFICATES_ARGS_TEMPLATE\
+    "db=\"%s\" use_hw=no soft=(,Virtual Reader,CAC,,%s,%s,%s)"
+
+static int wrap_vcard_emul_init(VCardEmulOptions *options)
+{
+    static int called;
+    static int options_was_null;
+
+    if (called) {
+        if ((options == NULL) != options_was_null) {
+            printf("%s: warning: running emulated with certificates"
+                   " and emulated side by side is not supported\n",
+                   __func__);
+            return VCARD_EMUL_FAIL;
+        }
+        vcard_emul_replay_insertion_events();
+        return VCARD_EMUL_OK;
+    }
+    options_was_null = (options == NULL);
+    called = 1;
+    return vcard_emul_init(options);
+}
+
+static int emulated_initialize_vcard_from_certificates(EmulatedState *card)
+{
+    char emul_args[200];
+    VCardEmulOptions *options = NULL;
+
+    snprintf(emul_args, sizeof(emul_args) - 1, CERTIFICATES_ARGS_TEMPLATE,
+        card->db ? card->db : CERTIFICATES_DEFAULT_DB,
+        card->cert1, card->cert2, card->cert3);
+    options = vcard_emul_options(emul_args);
+    if (options == NULL) {
+        printf("%s: warning: not using certificates due to"
+               " initialization error\n", __func__);
+    }
+    return wrap_vcard_emul_init(options);
+}
+
+typedef struct EnumTable {
+    const char *name;
+    uint32_t value;
+} EnumTable;
+
+EnumTable backend_enum_table[] = {
+    {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
+    {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
+    {NULL, 0},
+};
+
+static uint32_t parse_enumeration(char *str,
+    EnumTable *table, uint32_t not_found_value)
+{
+    uint32_t ret = not_found_value;
+
+    while (table->name != NULL) {
+        if (strcmp(table->name, str) == 0) {
+            ret = table->value;
+            break;
+        }
+        table++;
+    }
+    return ret;
+}
+
+static int emulated_initfn(CCIDCardState *base)
+{
+    EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
+    QemuThread thread_id;
+    VCardEmulError ret;
+    EnumTable *ptable;
+
+    QSIMPLEQ_INIT(&card->event_list);
+    QSIMPLEQ_INIT(&card->guest_apdu_list);
+    qemu_mutex_init(&card->event_list_mutex);
+    qemu_mutex_init(&card->vreader_mutex);
+    qemu_mutex_init(&card->handle_apdu_mutex);
+    qemu_cond_init(&card->handle_apdu_cond);
+    card->reader = NULL;
+    card->quit_apdu_thread = 0;
+    if (init_pipe_signaling(card) < 0) {
+        return -1;
+    }
+    card->backend = parse_enumeration(card->backend_str, backend_enum_table, 0);
+    if (card->backend == 0) {
+        printf("unknown backend, must be one of:\n");
+        for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) {
+            printf("%s\n", ptable->name);
+        }
+        return -1;
+    }
+
+    /* TODO: a passthru backened that works on local machine. third card type?*/
+    if (card->backend == BACKEND_CERTIFICATES) {
+        if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) {
+            ret = emulated_initialize_vcard_from_certificates(card);
+        } else {
+            printf("%s: you must provide all three certs for"
+                   " certificates backend\n", EMULATED_DEV_NAME);
+            return -1;
+        }
+    } else {
+        if (card->backend != BACKEND_NSS_EMULATED) {
+            printf("%s: bad backend specified. The options are:\n%s (default),"
+                " %s.\n", EMULATED_DEV_NAME, BACKEND_NSS_EMULATED_NAME,
+                BACKEND_CERTIFICATES_NAME);
+            return -1;
+        }
+        if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) {
+            printf("%s: unexpected cert parameters to nss emulated backend\n",
+                   EMULATED_DEV_NAME);
+            return -1;
+        }
+        /* default to mirroring the local hardware readers */
+        ret = wrap_vcard_emul_init(NULL);
+    }
+    if (ret != VCARD_EMUL_OK) {
+        printf("%s: failed to initialize vcard\n", EMULATED_DEV_NAME);
+        return -1;
+    }
+    qemu_thread_create(&thread_id, event_thread, card);
+    qemu_thread_create(&thread_id, handle_apdu_thread, card);
+    return 0;
+}
+
+static int emulated_exitfn(CCIDCardState *base)
+{
+    EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
+    VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
+
+    vevent_queue_vevent(vevent); /* stop vevent thread */
+    qemu_mutex_lock(&card->apdu_thread_quit_mutex);
+    card->quit_apdu_thread = 1; /* stop handle_apdu thread */
+    qemu_cond_signal(&card->handle_apdu_cond);
+    qemu_cond_wait(&card->apdu_thread_quit_cond,
+                      &card->apdu_thread_quit_mutex);
+    /* handle_apdu thread stopped, can destroy all of it's mutexes */
+    qemu_cond_destroy(&card->handle_apdu_cond);
+    qemu_cond_destroy(&card->apdu_thread_quit_cond);
+    qemu_mutex_destroy(&card->apdu_thread_quit_mutex);
+    qemu_mutex_destroy(&card->handle_apdu_mutex);
+    qemu_mutex_destroy(&card->vreader_mutex);
+    qemu_mutex_destroy(&card->event_list_mutex);
+    return 0;
+}
+
+static CCIDCardInfo emulated_card_info = {
+    .qdev.name = EMULATED_DEV_NAME,
+    .qdev.desc = "emulated smartcard",
+    .qdev.size = sizeof(EmulatedState),
+    .initfn = emulated_initfn,
+    .exitfn = emulated_exitfn,
+    .get_atr = emulated_get_atr,
+    .apdu_from_guest = emulated_apdu_from_guest,
+    .qdev.unplug    = qdev_simple_unplug_cb,
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_STRING("backend", EmulatedState, backend_str),
+        DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
+        DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
+        DEFINE_PROP_STRING("cert3", EmulatedState, cert3),
+        DEFINE_PROP_STRING("db", EmulatedState, db),
+        DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void ccid_card_emulated_register_devices(void)
+{
+    ccid_card_qdev_register(&emulated_card_info);
+}
+
+device_init(ccid_card_emulated_register_devices)
commit 65794b435c7a3e5945bd78fad8011e3f0f15f668
Author: Robert Relyea <rrelyea at redhat.com>
Date:   Thu Mar 17 16:39:46 2011 +0200

    libcacard: add docs

diff --git a/docs/libcacard.txt b/docs/libcacard.txt
new file mode 100644
index 0000000..5dee6fa
--- /dev/null
+++ b/docs/libcacard.txt
@@ -0,0 +1,483 @@
+This file documents the CAC (Common Access Card) library in the libcacard
+subdirectory.
+
+Virtual Smart Card Emulator
+
+This emulator is designed to provide emulation of actual smart cards to a
+virtual card reader running in a guest virtual machine. The emulated smart
+cards can be representations of real smart cards, where the necessary functions
+such as signing, card removal/insertion, etc. are mapped to real, physical
+cards which are shared with the client machine the emulator is running on, or
+the cards could be pure software constructs.
+
+The emulator is structured to allow multiple replacable or additional pieces,
+so it can be easily modified for future requirements. The primary envisioned
+modifications are:
+
+1) The socket connection to the virtual card reader (presumably a CCID reader,
+but other ISO-7816 compatible readers could be used). The code that handles
+this is in vscclient.c.
+
+2) The virtual card low level emulation. This is currently supplied by using
+NSS. This emulation could be replaced by implementations based on other
+security libraries, including but not limitted to openssl+pkcs#11 library,
+raw pkcs#11, Microsoft CAPI, direct opensc calls, etc. The code that handles
+this is in vcard_emul_nss.c.
+
+3) Emulation for new types of cards. The current implementation emulates the
+original DoD CAC standard with separate pki containers. This emulator lives in
+cac.c. More than one card type emulator could be included. Other cards could
+be emulated as well, including PIV, newer versions of CAC, PKCS #15, etc.
+
+--------------------
+Replacing the Socket Based Virtual Reader Interface.
+
+The current implementation contains a replacable module vscclient.c. The
+current vscclient.c implements a sockets interface to the virtual ccid reader
+on the guest. CCID commands that are pertinent to emulation are passed
+across the socket, and their responses are passed back along that same socket.
+The protocol that vscclient uses is defined in vscard_common.h and connects
+to a qemu ccid usb device. Since this socket runs as a client, vscclient.c
+implements a program with a main entry. It also handles argument parsing for
+the emulator.
+
+An application that wants to use the virtual reader can replace vscclient.c
+with it's own implementation that connects to it's own CCID reader.  The calls
+that the CCID reader can call are:
+
+      VReaderList * vreader_get_reader_list();
+
+  This function returns a list of virtual readers.  These readers may map to
+  physical devices, or simulated devices depending on vcard the back end. Each
+  reader in the list should represent a reader to the virtual machine. Virtual
+  USB address mapping is left to the CCID reader front end. This call can be
+  made any time to get an updated list. The returned list is a copy of the
+  internal list that can be referenced by the caller without locking. This copy
+  must be freed by the caller with vreader_list_delete when it is no longer
+  needed.
+
+      VReaderListEntry *vreader_list_get_first(VReaderList *);
+
+  This function gets the first entry on the reader list. Along with
+  vreader_list_get_next(), vreader_list_get_first() can be used to walk the
+  reader list returned from vreader_get_reader_list(). VReaderListEntries are
+  part of the list themselves and do not need to be freed separately from the
+  list. If there are no entries on the list, it will return NULL.
+
+      VReaderListEntry *vreader_list_get_next(VReaderListEntry *);
+
+  This function gets the next entry in the list. If there are no more entries
+  it will return NULL.
+
+      VReader * vreader_list_get_reader(VReaderListEntry *)
+
+  This function returns the reader stored in the reader List entry. Caller gets
+  a new reference to a reader. The caller must free it's reference when it is
+  finished with vreader_free().
+
+      void vreader_free(VReader *reader);
+
+   This function frees a reference to a reader. Reader's are reference counted
+   and are automatically deleted when the last reference is freed.
+
+      void vreader_list_delete(VReaderList *list);
+
+   This function frees the list, all the elements on the list, and all the
+   reader references held by the list.
+
+      VReaderStatus vreader_power_on(VReader *reader, char *atr, int *len);
+
+  This functions simulates a card power on. Virtual cards do not care about
+  the actual voltage and other physical parameters, but it does care that the
+  card is actually on or off. Cycling the card causes the card to reset. If
+  the caller provides enough space, vreader_power_on will return the ATR of
+  the virtual card. The amount of space provided in atr should be indicated
+  in *len. The function modifies *len to be the actual length of of the
+  returned ATR.
+
+      VReaderStatus vreader_power_off(VReader *reader);
+
+  This function simulates a power off of a virtual card.
+
+      VReaderStatus vreader_xfer_bytes(VReader *reader, unsigne char *send_buf,
+                                       int send_buf_len,
+                                       unsigned char *receive_buf,
+                                       int receive_buf_len);
+
+  This functions send a raw apdu to a card and returns the card's response.
+  The CCID front end should return the response back. Most of the emulation
+  is driven from these APDUs.
+
+      VReaderStatus vreader_card_is_present(VReader *reader);
+
+  This function returns whether or not the reader has a card inserted. The
+  vreader_power_on, vreader_power_off, and vreader_xfer_bytes will return
+  VREADER_NO_CARD.
+
+       const char *vreader_get_name(VReader *reader);
+
+  This function returns the name of the reader. The name comes from the card
+  emulator level and is usually related to the name of the physical reader.
+
+       VReaderID vreader_get_id(VReader *reader);
+
+  This function returns the id of a reader. All readers start out with an id
+  of -1. The application can set the id with vreader_set_id.
+
+       VReaderStatus vreader_get_id(VReader *reader, VReaderID id);
+
+  This function sets the reader id. The application is responsible for making
+  sure that the id is unique for all readers it is actively using.
+
+       VReader *vreader_find_reader_by_id(VReaderID id);
+
+  This function returns the reader which matches the id. If two readers match,
+  only one is returned. The function returns NULL if the id is -1.
+
+       Event *vevent_wait_next_vevent();
+
+  This function blocks waiting for reader and card insertion events. There
+  will be one event for each card insertion, each card removal, each reader
+  insertion and each reader removal. At start up, events are created for all
+  the initial readers found, as well as all the cards that are inserted.
+
+       Event *vevent_get_next_vevent();
+
+  This function returns a pending event if it exists, otherwise it returns
+  NULL. It does not block.
+
+----------------
+Card Type Emulator: Adding a New Virtual Card Type
+
+The ISO 7816 card spec describes 2 types of cards:
+ 1) File system cards, where the smartcard is managed by reading and writing
+data to files in a file system. There is currently only boiler plate
+implemented for file system cards.
+ 2) VM cards, where the card has loadable applets which perform the card
+functions. The current implementation supports VM cards.
+
+In the case of VM cards, the difference between various types of cards is
+really what applets have been installed in that card. This structure is
+mirrored in card type emulators. The 7816 emulator already handles the basic
+ISO 7186 commands. Card type emulators simply need to add the virtual applets
+which emulate the real card applets. Card type emulators have exactly one
+public entry point:
+
+       VCARDStatus xxx_card_init(VCard *card, const char *flags,
+                               const unsigned char *cert[],
+                               int cert_len[],
+                               VCardKey *key[],
+                               int cert_count);
+
+  The parameters for this are:
+  card       - the virtual card structure which will prepresent this card.
+  flags      - option flags that may be specific to this card type.
+  cert       - array of binary certificates.
+  cert_len   - array of lengths of each of the certificates specified in cert.
+  key        - array of opaque key structures representing the private keys on
+               the card.
+  cert_count - number of entries in cert, cert_len, and key arrays.
+
+  Any cert, cert_len, or key with the same index are matching sets. That is
+  cert[0] is cert_len[0] long and has the corresponsing private key of key[0].
+
+The card type emulator is expected to own the VCardKeys, but it should copy
+any raw cert data it wants to save. It can create new applets and add them to
+the card using the following functions:
+
+       VCardApplet *vcard_new_applet(VCardProcessAPDU apdu_func,
+                                     VCardResetApplet reset_func,
+                                     const unsigned char *aid,
+                                     int aid_len);
+
+  This function creates a new applet. Applet structures store the following
+  information:
+     1) the AID of the applet (set by aid and aid_len).
+     2) a function to handle APDUs for this applet. (set by apdu_func, more on
+        this below).
+     3) a function to reset the applet state when the applet is selected.
+        (set by reset_func, more on this below).
+     3) applet private data, a data pointer used by the card type emulator to
+        store any data or state it needs to complete requests. (set by a
+        separate call).
+     4) applet private data free, a function used to free the applet private
+        data when the applet itself is destroyed.
+  The created applet can be added to the card with vcard_add_applet below.
+
+        void vcard_set_applet_private(VCardApplet *applet,
+                                      VCardAppletPrivate *private,
+                                      VCardAppletPrivateFree private_free);
+  This function sets the private data and the corresponding free function.
+  VCardAppletPrivate is an opaque data structure to the rest of the emulator.
+  The card type emulator can define it any way it wants by defining
+  struct VCardAppletPrivateStruct {};. If there is already a private data
+  structure on the applet, the old one is freed before the new one is set up.
+  passing two NULL clear any existing private data.
+
+         VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
+
+  Add an applet onto the list of applets attached to the card. Once an applet
+  has been added, it can be selected by it's aid, and then commands will be
+  routed to it VCardProcessAPDU function. This function adopts the applet the
+  passed int applet. Note: 2 applets with the same AID should not be added to
+  the same card. It's permissible to add more than one applet. Multiple applets
+  may have the same VCardPRocessAPDU entry point.
+
+The certs and keys should be attached to private data associated with one or
+more appropriate applets for that card. Control will come to the card type
+emulators once one of its applets are selected through the VCardProcessAPDU
+function it specified when it created the applet.
+
+The signature of VCardResetApplet is:
+        VCardStatus (*VCardResetApplet) (VCard *card, int channel);
+  This function will reset the any internal applet state that needs to be
+  cleared after a select applet call. It should return VCARD_DONE;
+
+The signature of VCardProcessAPDU is:
+        VCardStatus (*VCardProcessAPDU)(VCard *card, VCardAPDU *apdu,
+                                         VCardResponse **response);
+  This function examines the APDU and determines whether it should process
+  the apdu directly, reject the apdu as invalid, or pass the apdu on to
+  the basic 7816 emulator for processing.
+      If the 7816 emulator should process the apdu, then the VCardProcessAPDU
+  should return VCARD_NEXT.
+      If there is an error, then VCardProcessAPDU should return an error
+  response using vcard_make_response and the appropriate 7816 error code
+  (see card_7816t.h) or vcard_make_response with a card type specific error
+  code. It should then return VCARD_DONE.
+      If the apdu can be processed correctly, VCardProcessAPDU should do so,
+  set the response value appropriately for that APDU, and return VCARD_DONE.
+  VCardProcessAPDU should always set the response if it returns VCARD_DONE.
+  It should always either return VCARD_DONE or VCARD_NEXT.
+
+Parsing the APDU --
+
+Prior to processing calling the card type emulator's VCardProcessAPDU function, the emulator has already decoded the APDU header and set several fields:
+
+   apdu->a_data - The raw apdu data bytes.
+   apdu->a_len  - The len of the raw apdu data.
+   apdu->a_body - The start of any post header parameter data.
+   apdu->a_Lc   - The parameter length value.
+   apdu->a_Le   - The expected length of any returned data.
+   apdu->a_cla  - The raw apdu class.
+   apdu->a_channel - The channel (decoded from the class).
+   apdu->a_secure_messaging_type - The decoded secure messagin type
+                                   (from class).
+   apdu->a_type - The decode class type.
+   apdu->a_gen_type - the generic class type (7816, PROPRIETARY, RFU, PTS).
+   apdu->a_ins  - The instruction byte.
+   apdu->a_p1   - Parameter 1.
+   apdu->a_p2   - Parameter 2.
+
+Creating a Response --
+
+The expected result of any APDU call is a response. The card type emulator must
+set *response with an appropriate VCardResponse value if it returns VCARD_DONE.
+Reponses could be as simple as returning a 2 byte status word response, to as
+complex as returning a block of data along with a 2 byte response. Which is
+returned will depend on the semantics of the APDU. The following functions will
+create card responses.
+
+        VCardResponse *vcard_make_response(VCard7816Status status);
+
+    This is the most basic function to get a response. This function will
+    return a response the consists soley one 2 byte status code. If that status
+    code is defined in card_7816t.h, then this function is guarrenteed to
+    return a response with that status. If a cart type specific status code
+    is passed and vcard_make_response fails to allocate the appropriate memory
+    for that response, then vcard_make_response will return a VCardResponse
+    of VCARD7816_STATUS_EXC_ERROR_MEMORY. In any case, this function is
+    guarrenteed to return a valid VCardResponse.
+
+        VCardResponse *vcard_response_new(unsigned char *buf, int len,
+                                          VCard7816Status status);
+
+    This function is similar to vcard_make_response except it includes some
+    returned data with the response. It could also fail to allocate enough
+    memory, in which case it will return NULL.
+
+        VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
+                                                       unsigned char sw2);
+
+    Sometimes in 7816 the response bytes are treated as two separate bytes with
+    split meanings. This function allows you to create a response based on
+    two separate bytes. This function could fail, in which case it will return
+    NULL.
+
+       VCardResponse *vcard_response_new_bytes(unsigned char *buf, int len,
+                                               unsigned char sw1,
+                                               unsigned char sw2);
+
+    This function is the same as vcard_response_new except you may specify
+    the status as two separate bytes like vcard_response_new_status_bytes.
+
+
+Implementing functionality ---
+
+The following helper functions access information about the current card
+and applet.
+
+        VCARDAppletPrivate *vcard_get_current_applet_private(VCard *card,
+                                                             int channel);
+
+    This function returns any private data set by the card type emulator on
+    the currently selected applet. The card type emulator keeps track of the
+    current applet state in this data structure. Any certs and keys associated
+    with a particular applet is also stored here.
+
+        int vcard_emul_get_login_count(VCard *card);
+
+    This function returns the the number of remaing login attempts for this
+    card. If the card emulator does not know, or the card does not have a
+    way of giving this information, this function returns -1.
+
+
+         VCard7816Status vcard_emul_login(VCard *card, unsigned char *pin,
+                                          int pin_len);
+
+    This function logins into the card and return the standard 7816 status
+    word depending on the success or failure of the call.
+
+         void vcard_emul_delete_key(VCardKey *key);
+
+     This function frees the VCardKey passed in to xxxx_card_init. The card
+     type emulator is responsible for freeing this key when it no longer needs
+     it.
+
+         VCard7816Status vcard_emul_rsa_op(VCard *card, VCardKey *key,
+                                           unsigned char *buffer,
+                                           int buffer_size);
+
+     This function does a raw rsa op on the buffer with the given key.
+
+The sample card type emulator is found in cac.c. It implements the cac specific
+applets.  Only those applets needed by the coolkey pkcs#11 driver on the guest
+have been implemented. To support the full range CAC middleware, a complete CAC
+card according to the CAC specs should be implemented here.
+
+------------------------------
+Virtual Card Emulator
+
+This code accesses both real smart cards and simulated smart cards through
+services provided on the client. The current implementation uses NSS, which
+already knows how to talk to various PKCS #11 modules on the client, and is
+portable to most operating systems. A particular emulator can have only one
+virtual card implementation at a time.
+
+The virtual card emulator consists of a series of virtual card services. In
+addition to the services describe above (services starting with
+vcard_emul_xxxx), the virtual card emulator also provides the following
+functions:
+
+    VCardEmulError vcard_emul_init(cont VCardEmulOptions *options);
+
+  The options structure is built by another function in the virtual card
+  interface where a string of virtual card emulator specific strings are
+  mapped to the options. The actual structure is defined by the virutal card
+  emulator and is used to determine the configuration of soft cards, or to
+  determine which physical cards to present to the guest.
+
+  The vcard_emul_init function will build up sets of readers, create any
+  threads that are needed to watch for changes in the reader state. If readers
+  have cards present in them, they are also initialized.
+
+  Readers are created with the function.
+
+          VReader *vreader_new(VReaderEmul *reader_emul,
+                               VReaderEmulFree reader_emul_free);
+
+      The freeFunc is used to free the VReaderEmul * when the reader is
+      destroyed.  The VReaderEmul structure is an opaque structure to the
+      rest of the code, but defined by the virtual card emulator, which can
+      use it to store any reader specific state.
+
+  Once the reader has been created, it can be added to the front end with the
+  call:
+
+           VReaderStatus vreader_add_reader(VReader *reader);
+
+      This function will automatically generate the appropriate new reader
+      events and add the reader to the list.
+
+  To create a new card, the virtual card emulator will call a similiar
+  function.
+
+           VCard *vcard_new(VCardEmul *card_emul,
+                            VCardEmulFree card_emul_free);
+
+      Like vreader_new, this function takes a virtual card emulator specific
+      structure which it uses to keep track of the card state.
+
+  Once the card is created, it is attached to a card type emulator with the
+  following function:
+
+            VCardStatus vcard_init(VCard *vcard, VCardEmulType type,
+                                   const char *flags,
+                                   unsigned char *const *certs,
+                                   int *cert_len,
+                                   VCardKey *key[],
+                                   int cert_count);
+
+      The vcard is the value returned from vcard_new. The type is the
+      card type emulator that this card should presented to the guest as.
+      The flags are card type emulator specific options. The certs,
+      cert_len, and keys are all arrays of length cert_count. These are the
+      the same of the parameters xxxx_card_init() accepts.
+
+   Finally the card is associated with it's reader by the call:
+
+            VReaderStatus vreader_insert_card(VReader *vreader, VCard *vcard);
+
+      This function, like vreader_add_reader, will take care of any event
+      notification for the card insert.
+
+
+    VCardEmulError vcard_emul_force_card_remove(VReader *vreader);
+
+  Force a card that is present to appear to be removed to the guest, even if
+  that card is a physical card and is present.
+
+
+    VCardEmulError vcard_emul_force_card_insert(VReader *reader);
+
+  Force a card that has been removed by vcard_emul_force_card_remove to be
+  reinserted from the point of view of the guest. This will only work if the
+  card is physically present (which is always true fro a soft card).
+
+     void vcard_emul_get_atr(Vcard *card, unsigned char *atr, int *atr_len);
+
+  Return the virtual ATR for the card. By convention this should be the value
+  VCARD_ATR_PREFIX(size) followed by several ascii bytes related to this
+  particular emulator. For instance the NSS emulator returns
+  {VCARD_ATR_PREFIX(3), 'N', 'S', 'S' }. Do ot return more data then *atr_len;
+
+     void vcard_emul_reset(VCard *card, VCardPower power)
+
+   Set the state of 'card' to the current power level and reset its internal
+   state (logout, etc).
+
+-------------------------------------------------------
+List of files and their function:
+README - This file
+card_7816.c - emulate basic 7816 functionality. Parse APDUs.
+card_7816.h - apdu and response services definitions.
+card_7816t.h - 7816 specific structures, types and definitions.
+event.c - event handling code.
+event.h - event handling services definitions.
+eventt.h - event handling structures and types
+vcard.c - handle common virtual card services like creation, destruction, and
+          applet management.
+vcard.h - common virtual card services function definitions.
+vcardt.h - comon virtual card types
+vreader.c - common virtual reader services.
+vreader.h - common virtual reader services definitions.
+vreadert.h - comon virtual reader types.
+vcard_emul_type.c - manage the card type emulators.
+vcard_emul_type.h - definitions for card type emulators.
+cac.c - card type emulator for CAC cards
+vcard_emul.h - virtual card emulator service definitions.
+vcard_emul_nss.c - virtual card emulator implementation for nss.
+vscclient.c - socket connection to guest qemu usb driver.
+vscard_common.h - common header with the guest qemu usb driver.
+mutex.h - header file for machine independent mutexes.
+link_test.c - static test to make sure all the symbols are properly defined.
commit 2ac85b93b0487b362188a62eef685e6f9e7729ce
Author: Robert Relyea <rrelyea at redhat.com>
Date:   Thu Mar 17 16:38:30 2011 +0200

    libcacard: add vscclient
    
    client to talk to ccid-card-passthru and use smartcard on client to
    perform actual operations.
    
    v23->v24 changes: (Jes Sorensen review 2)
     * use qemu_socket instead of socket
     * use fprintf(stderr,..) for errors
     * remove unneccessary includes since using qemu_common.h

diff --git a/libcacard/Makefile b/libcacard/Makefile
index 0211eac..4010029 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -15,6 +15,11 @@ QEMU_OBJS=$(addprefix ../, $(QEMU_THREAD) $(oslib-obj-y) $(trace-obj-y) qemu-mal
 
 QEMU_CFLAGS+=-I../
 
+vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
+	$(call quiet-command,$(CC) $(libcacard_libs) -lrt -o $@ $^,"  LINK  $(TARGET_DIR)$@")
+
+all: vscclient
+
 clean:
-	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
+	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient
 
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
new file mode 100644
index 0000000..ce33f5a
--- /dev/null
+++ b/libcacard/vscclient.c
@@ -0,0 +1,652 @@
+/*
+ * Tester for VSCARD protocol, client side.
+ *
+ * Can be used with ccid-card-passthru.
+ *
+ * Copyright (c) 2011 Red Hat.
+ * Written by Alon Levy.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <netdb.h>
+
+#include "qemu-common.h"
+#include "qemu-thread.h"
+#include "qemu_socket.h"
+
+#include "vscard_common.h"
+
+#include "vreader.h"
+#include "vcard_emul.h"
+#include "vevent.h"
+
+int verbose;
+
+int sock;
+
+static void
+print_byte_array(
+    uint8_t *arrBytes,
+    unsigned int nSize
+) {
+    int i;
+    for (i = 0; i < nSize; i++) {
+        printf("%02X ", arrBytes[i]);
+    }
+    printf("\n");
+}
+
+static void
+print_usage(void) {
+    printf("vscclient [-c <certname> .. -e <emul_args> -d <level>%s] "
+            "<host> <port>\n",
+#ifdef USE_PASSTHRU
+    " -p");
+    printf(" -p use passthrough mode\n");
+#else
+   "");
+#endif
+    vcard_emul_usage();
+}
+
+static QemuMutex write_lock;
+
+static int
+send_msg(
+    VSCMsgType type,
+    uint32_t reader_id,
+    const void *msg,
+    unsigned int length
+) {
+    int rv;
+    VSCMsgHeader mhHeader;
+
+    qemu_mutex_lock(&write_lock);
+
+    if (verbose > 10) {
+        printf("sending type=%d id=%d, len =%d (0x%x)\n",
+               type, reader_id, length, length);
+    }
+
+    mhHeader.type = htonl(type);
+    mhHeader.reader_id = 0;
+    mhHeader.length = htonl(length);
+    rv = write(sock, &mhHeader, sizeof(mhHeader));
+    if (rv < 0) {
+        /* Error */
+        fprintf(stderr, "write header error\n");
+        close(sock);
+        qemu_mutex_unlock(&write_lock);
+        return 16;
+    }
+    rv = write(sock, msg, length);
+    if (rv < 0) {
+        /* Error */
+        fprintf(stderr, "write error\n");
+        close(sock);
+        qemu_mutex_unlock(&write_lock);
+        return 16;
+    }
+    qemu_mutex_unlock(&write_lock);
+
+    return 0;
+}
+
+static VReader *pending_reader;
+static QemuMutex pending_reader_lock;
+static QemuCond pending_reader_condition;
+
+#define MAX_ATR_LEN 40
+static void *
+event_thread(void *arg)
+{
+    unsigned char atr[MAX_ATR_LEN];
+    int atr_len = MAX_ATR_LEN;
+    VEvent *event = NULL;
+    unsigned int reader_id;
+
+
+    while (1) {
+        const char *reader_name;
+
+        event = vevent_wait_next_vevent();
+        if (event == NULL) {
+            break;
+        }
+        reader_id = vreader_get_id(event->reader);
+        if (reader_id == VSCARD_UNDEFINED_READER_ID &&
+            event->type != VEVENT_READER_INSERT) {
+            /* ignore events from readers qemu has rejected */
+            /* if qemu is still deciding on this reader, wait to see if need to
+             * forward this event */
+            qemu_mutex_lock(&pending_reader_lock);
+            if (!pending_reader || (pending_reader != event->reader)) {
+                /* wasn't for a pending reader, this reader has already been
+                 * rejected by qemu */
+                qemu_mutex_unlock(&pending_reader_lock);
+                vevent_delete(event);
+                continue;
+            }
+            /* this reader hasn't been told it's status from qemu yet, wait for
+             * that status */
+            while (pending_reader != NULL) {
+                qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
+            }
+            qemu_mutex_unlock(&pending_reader_lock);
+            /* now recheck the id */
+            reader_id = vreader_get_id(event->reader);
+            if (reader_id == VSCARD_UNDEFINED_READER_ID) {
+                /* this reader was rejected */
+                vevent_delete(event);
+                continue;
+            }
+            /* reader was accepted, now forward the event */
+        }
+        switch (event->type) {
+        case VEVENT_READER_INSERT:
+            /* tell qemu to insert a new CCID reader */
+            /* wait until qemu has responded to our first reader insert
+             * before we send a second. That way we won't confuse the responses
+             * */
+            qemu_mutex_lock(&pending_reader_lock);
+            while (pending_reader != NULL) {
+                qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
+            }
+            pending_reader = vreader_reference(event->reader);
+            qemu_mutex_unlock(&pending_reader_lock);
+            reader_name = vreader_get_name(event->reader);
+            if (verbose > 10) {
+                printf(" READER INSERT: %s\n", reader_name);
+            }
+            send_msg(VSC_ReaderAdd,
+                reader_id, /* currerntly VSCARD_UNDEFINED_READER_ID */
+                NULL, 0 /* TODO reader_name, strlen(reader_name) */);
+            break;
+        case VEVENT_READER_REMOVE:
+            /* future, tell qemu that an old CCID reader has been removed */
+            if (verbose > 10) {
+                printf(" READER REMOVE: %d\n", reader_id);
+            }
+            send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
+            break;
+        case VEVENT_CARD_INSERT:
+            /* get the ATR (intended as a response to a power on from the
+             * reader */
+            atr_len = MAX_ATR_LEN;
+            vreader_power_on(event->reader, atr, &atr_len);
+            /* ATR call functions as a Card Insert event */
+            if (verbose > 10) {
+                printf(" CARD INSERT %d: ", reader_id);
+                print_byte_array(atr, atr_len);
+            }
+            send_msg(VSC_ATR, reader_id, atr, atr_len);
+            break;
+        case VEVENT_CARD_REMOVE:
+            /* Card removed */
+            if (verbose > 10) {
+                printf(" CARD REMOVE %d:\n", reader_id);
+            }
+            send_msg(VSC_CardRemove, reader_id, NULL, 0);
+            break;
+        default:
+            break;
+        }
+        vevent_delete(event);
+    }
+    return NULL;
+}
+
+
+static unsigned int
+get_id_from_string(char *string, unsigned int default_id)
+{
+    unsigned int id = atoi(string);
+
+    /* don't accidentally swith to zero because no numbers have been supplied */
+    if ((id == 0) && *string != '0') {
+        return default_id;
+    }
+    return id;
+}
+
+static void
+do_command(void)
+{
+    char inbuf[255];
+    char *string;
+    VCardEmulError error;
+    static unsigned int default_reader_id;
+    unsigned int reader_id;
+    VReader *reader = NULL;
+
+    reader_id = default_reader_id;
+    string = fgets(inbuf, sizeof(inbuf), stdin);
+    if (string != NULL) {
+        if (strncmp(string, "exit", 4) == 0) {
+            /* remove all the readers */
+            VReaderList *list = vreader_get_reader_list();
+            VReaderListEntry *reader_entry;
+            printf("Active Readers:\n");
+            for (reader_entry = vreader_list_get_first(list); reader_entry;
+                 reader_entry = vreader_list_get_next(reader_entry)) {
+                VReader *reader = vreader_list_get_reader(reader_entry);
+                vreader_id_t reader_id;
+                reader_id = vreader_get_id(reader);
+                if (reader_id == -1) {
+                    continue;
+                }
+                /* be nice and signal card removal first (qemu probably should
+                 * do this itself) */
+                if (vreader_card_is_present(reader) == VREADER_OK) {
+                    send_msg(VSC_CardRemove, reader_id, NULL, 0);
+                }
+                send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
+            }
+            exit(0);
+        } else if (strncmp(string, "insert", 6) == 0) {
+            if (string[6] == ' ') {
+                reader_id = get_id_from_string(&string[7], reader_id);
+            }
+            reader = vreader_get_reader_by_id(reader_id);
+            if (reader != NULL) {
+                error = vcard_emul_force_card_insert(reader);
+                printf("insert %s, returned %d\n",
+                       reader ? vreader_get_name(reader)
+                       : "invalid reader", error);
+            } else {
+                printf("no reader by id %d found\n", reader_id);
+            }
+        } else if (strncmp(string, "remove", 6) == 0) {
+            if (string[6] == ' ') {
+                reader_id = get_id_from_string(&string[7], reader_id);
+            }
+            reader = vreader_get_reader_by_id(reader_id);
+            if (reader != NULL) {
+                error = vcard_emul_force_card_remove(reader);
+                printf("remove %s, returned %d\n",
+                        reader ? vreader_get_name(reader)
+                        : "invalid reader", error);
+            } else {
+                printf("no reader by id %d found\n", reader_id);
+            }
+        } else if (strncmp(string, "select", 6) == 0) {
+            if (string[6] == ' ') {
+                reader_id = get_id_from_string(&string[7],
+                                               VSCARD_UNDEFINED_READER_ID);
+            }
+            if (reader_id != VSCARD_UNDEFINED_READER_ID) {
+                reader = vreader_get_reader_by_id(reader_id);
+            }
+            if (reader) {
+                printf("Selecting reader %d, %s\n", reader_id,
+                        vreader_get_name(reader));
+                default_reader_id = reader_id;
+            } else {
+                printf("Reader with id %d not found\n", reader_id);
+            }
+        } else if (strncmp(string, "debug", 5) == 0) {
+            if (string[5] == ' ') {
+                verbose = get_id_from_string(&string[6], 0);
+            }
+            printf("debug level = %d\n", verbose);
+        } else if (strncmp(string, "list", 4) == 0) {
+            VReaderList *list = vreader_get_reader_list();
+            VReaderListEntry *reader_entry;
+            printf("Active Readers:\n");
+            for (reader_entry = vreader_list_get_first(list); reader_entry;
+                 reader_entry = vreader_list_get_next(reader_entry)) {
+                VReader *reader = vreader_list_get_reader(reader_entry);
+                vreader_id_t reader_id;
+                reader_id = vreader_get_id(reader);
+                if (reader_id == -1) {
+                    continue;
+                }
+                printf("%3d %s %s\n", reader_id,
+                       vreader_card_is_present(reader) == VREADER_OK ?
+                       "CARD_PRESENT" : "            ",
+                       vreader_get_name(reader));
+            }
+            printf("Inactive Readers:\n");
+            for (reader_entry = vreader_list_get_first(list); reader_entry;
+                 reader_entry = vreader_list_get_next(reader_entry)) {
+                VReader *reader = vreader_list_get_reader(reader_entry);
+                vreader_id_t reader_id;
+                reader_id = vreader_get_id(reader);
+                if (reader_id != -1) {
+                    continue;
+                }
+
+                printf("INA %s %s\n",
+                       vreader_card_is_present(reader) == VREADER_OK ?
+                       "CARD_PRESENT" : "            ",
+                       vreader_get_name(reader));
+            }
+        } else if (*string != 0) {
+            printf("valid commands:\n");
+            printf("insert [reader_id]\n");
+            printf("remove [reader_id]\n");
+            printf("select reader_id\n");
+            printf("list\n");
+            printf("debug [level]\n");
+            printf("exit\n");
+        }
+    }
+    vreader_free(reader);
+    printf("> ");
+    fflush(stdout);
+}
+
+
+#define APDUBufSize 270
+
+/* just for ease of parsing command line arguments. */
+#define MAX_CERTS 100
+
+static int
+connect_to_qemu(
+    const char *host,
+    const char *port
+) {
+    struct addrinfo hints;
+    struct addrinfo *server;
+    int ret;
+
+    sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
+    if (sock < 0) {
+        /* Error */
+        fprintf(stderr, "Error opening socket!\n");
+    }
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = 0;
+    hints.ai_protocol = 0;          /* Any protocol */
+
+    ret = getaddrinfo(host, port, &hints, &server);
+
+    if (ret != 0) {
+        /* Error */
+        fprintf(stderr, "getaddrinfo failed\n");
+        return 5;
+    }
+
+    if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
+        /* Error */
+        fprintf(stderr, "Could not connect\n");
+        return 5;
+    }
+    if (verbose) {
+        printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
+    }
+    return sock;
+}
+
+static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+{
+    uint32_t *capabilities = (incoming->capabilities);
+    int num_capabilities =
+        1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+    int i;
+    int rv;
+    pthread_t thread_id;
+
+    incoming->version = ntohl(incoming->version);
+    if (incoming->version != VSCARD_VERSION) {
+        if (verbose > 0) {
+            printf("warning: host has version %d, we have %d\n",
+                verbose, VSCARD_VERSION);
+        }
+    }
+    if (incoming->magic != VSCARD_MAGIC) {
+        printf("unexpected magic: got %d, expected %d\n",
+            incoming->magic, VSCARD_MAGIC);
+        return -1;
+    }
+    for (i = 0 ; i < num_capabilities; ++i) {
+        capabilities[i] = ntohl(capabilities[i]);
+    }
+    /* Future: check capabilities */
+    /* remove whatever reader might be left in qemu,
+     * in case of an unclean previous exit. */
+    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+    /* launch the event_thread. This will trigger reader adds for all the
+     * existing readers */
+    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+    if (rv < 0) {
+        perror("pthread_create");
+        return rv;
+    }
+    return 0;
+}
+
+int
+main(
+    int argc,
+    char *argv[]
+) {
+    char *qemu_host;
+    char *qemu_port;
+    VSCMsgHeader mhHeader;
+    VSCMsgError *error_msg;
+
+    int rv;
+    int dwSendLength;
+    int dwRecvLength;
+    uint8_t pbRecvBuffer[APDUBufSize];
+    uint8_t pbSendBuffer[APDUBufSize];
+     VReaderStatus reader_status;
+    VReader *reader = NULL;
+    VCardEmulOptions *command_line_options = NULL;
+
+    char *cert_names[MAX_CERTS];
+    char *emul_args = NULL;
+    int cert_count = 0;
+    int c;
+
+    while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
+        switch (c) {
+        case 'c':
+            if (cert_count >= MAX_CERTS) {
+                printf("too many certificates (max = %d)\n", MAX_CERTS);
+                exit(5);
+            }
+            cert_names[cert_count++] = optarg;
+            break;
+        case 'e':
+            emul_args = optarg;
+            break;
+        case 'p':
+            print_usage();
+            exit(4);
+            break;
+        case 'd':
+            verbose = get_id_from_string(optarg, 1);
+            break;
+        }
+    }
+
+    if (argc - optind != 2) {
+        print_usage();
+        exit(4);
+    }
+
+    if (cert_count > 0) {
+        char *new_args;
+        int len, i;
+        /* if we've given some -c options, we clearly we want do so some
+         * software emulation.  add that emulation now. this is NSS Emulator
+         * specific */
+        if (emul_args == NULL) {
+            emul_args = (char *)"db=\"/etc/pki/nssdb\"";
+        }
+#define SOFT_STRING ",soft=(,Virtual Reader,CAC,,"
+             /* 2 == close paren & null */
+        len = strlen(emul_args) + strlen(SOFT_STRING) + 2;
+        for (i = 0; i < cert_count; i++) {
+            len += strlen(cert_names[i])+1; /* 1 == comma */
+        }
+        new_args = qemu_malloc(len);
+        strcpy(new_args, emul_args);
+        strcat(new_args, SOFT_STRING);
+        for (i = 0; i < cert_count; i++) {
+            strcat(new_args, cert_names[i]);
+            strcat(new_args, ",");
+        }
+        strcat(new_args, ")");
+        emul_args = new_args;
+    }
+    if (emul_args) {
+        command_line_options = vcard_emul_options(emul_args);
+    }
+
+    qemu_host = strdup(argv[argc - 2]);
+    qemu_port = strdup(argv[argc - 1]);
+    sock = connect_to_qemu(qemu_host, qemu_port);
+
+    qemu_mutex_init(&write_lock);
+    qemu_mutex_init(&pending_reader_lock);
+    qemu_cond_init(&pending_reader_condition);
+
+    vcard_emul_init(command_line_options);
+
+    printf("> ");
+    fflush(stdout);
+
+    /* Send init message, Host responds (and then we send reader attachments) */
+    VSCMsgInit init = {
+        .version = htonl(VSCARD_VERSION),
+        .magic = VSCARD_MAGIC,
+        .capabilities = {0}
+    };
+    send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init));
+
+    do {
+        fd_set fds;
+
+        FD_ZERO(&fds);
+        FD_SET(1, &fds);
+        FD_SET(sock, &fds);
+
+        /* waiting on input from the socket */
+        rv = select(sock+1, &fds, NULL, NULL, NULL);
+        if (rv < 0) {
+            /* handle error */
+            perror("select");
+            return 7;
+        }
+        if (FD_ISSET(1, &fds)) {
+            do_command();
+        }
+        if (!FD_ISSET(sock, &fds)) {
+            continue;
+        }
+
+        rv = read(sock, &mhHeader, sizeof(mhHeader));
+        if (rv < sizeof(mhHeader)) {
+            /* Error */
+            if (rv < 0) {
+                perror("header read error\n");
+            } else {
+                fprintf(stderr, "header short read %d\n", rv);
+            }
+            return 8;
+        }
+        mhHeader.type = ntohl(mhHeader.type);
+        mhHeader.reader_id = ntohl(mhHeader.reader_id);
+        mhHeader.length = ntohl(mhHeader.length);
+        if (verbose) {
+            printf("Header: type=%d, reader_id=%d length=%d (0x%x)\n",
+                    mhHeader.type, mhHeader.reader_id, mhHeader.length,
+                                               mhHeader.length);
+        }
+        switch (mhHeader.type) {
+        case VSC_APDU:
+        case VSC_Flush:
+        case VSC_Error:
+        case VSC_Init:
+            rv = read(sock, pbSendBuffer, mhHeader.length);
+            break;
+        default:
+            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+            return 0;
+        }
+        switch (mhHeader.type) {
+        case VSC_APDU:
+            if (rv < 0) {
+                /* Error */
+                fprintf(stderr, "read error\n");
+                close(sock);
+                return 8;
+            }
+            if (verbose) {
+                printf(" recv APDU: ");
+                print_byte_array(pbSendBuffer, mhHeader.length);
+            }
+            /* Transmit recieved APDU */
+            dwSendLength = mhHeader.length;
+            dwRecvLength = sizeof(pbRecvBuffer);
+            reader = vreader_get_reader_by_id(mhHeader.reader_id);
+            reader_status = vreader_xfr_bytes(reader,
+                pbSendBuffer, dwSendLength,
+                pbRecvBuffer, &dwRecvLength);
+            if (reader_status == VREADER_OK) {
+                mhHeader.length = dwRecvLength;
+                if (verbose) {
+                    printf(" send response: ");
+                    print_byte_array(pbRecvBuffer, mhHeader.length);
+                }
+                send_msg(VSC_APDU, mhHeader.reader_id,
+                         pbRecvBuffer, dwRecvLength);
+            } else {
+                rv = reader_status; /* warning: not meaningful */
+                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+            }
+            vreader_free(reader);
+            reader = NULL; /* we've freed it, don't use it by accident
+                              again */
+            break;
+        case VSC_Flush:
+            /* TODO: actually flush */
+            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+            break;
+        case VSC_Error:
+            error_msg = (VSCMsgError *) pbSendBuffer;
+            if (error_msg->code == VSC_SUCCESS) {
+                qemu_mutex_lock(&pending_reader_lock);
+                if (pending_reader) {
+                    vreader_set_id(pending_reader, mhHeader.reader_id);
+                    vreader_free(pending_reader);
+                    pending_reader = NULL;
+                    qemu_cond_signal(&pending_reader_condition);
+                }
+                qemu_mutex_unlock(&pending_reader_lock);
+                break;
+            }
+            printf("warning: qemu refused to add reader\n");
+            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+                /* clear pending reader, qemu can't handle any more */
+                qemu_mutex_lock(&pending_reader_lock);
+                if (pending_reader) {
+                    pending_reader = NULL;
+                    /* make sure the event loop doesn't hang */
+                    qemu_cond_signal(&pending_reader_condition);
+                }
+                qemu_mutex_unlock(&pending_reader_lock);
+            }
+            break;
+        case VSC_Init:
+            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+                return -1;
+            }
+            break;
+        default:
+            printf("Default\n");
+            return 0;
+        }
+    } while (rv >= 0);
+
+    return 0;
+}
commit 111a38b018c86e6651750c5a548ad534f80b5bb5
Author: Robert Relyea <rrelyea at redhat.com>
Date:   Sun Nov 28 16:36:38 2010 +0200

    libcacard: initial commit
    
    libcacard emulates a Common Access Card (CAC) which is a standard
    for smartcards. It is used by the emulated ccid card introduced in
    a following patch. Docs are available in docs/libcacard.txt
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    ---
    
    changes from v24->v25:
     * Fix out of tree builds.
     * Fix build with linux-user targets.
    
    changes from v23->v24: (Jes Sorensen review 2)
     * Makefile.target: use obj-$(CONFIG_*) +=
     * remove unrequired includes, include qemu-common before qemu-thread
      * required adding #define NO_NSPR_10_SUPPORT (harmless)
    
    changes from v22->v23:
     * configure fixes: (reported by Stefan Hajnoczi)
      * test a = b, not a == b (second isn't portable)
      * quote $source_path in case it contains spaces
       - this doesn't really help since there are many other places
         that need similar fixes, not introduced by this patch.
    
    changes from v21->v22:
     * fix configure to not link libcacard if nss not found
        (reported by Stefan Hajnoczi)
     * fix vscclient linkage with simpletrace backend
        (reported by Stefan Hajnoczi)
     * card_7816.c: add missing break in ERROR_DATA_NOT_FOUND
        (reported by William van de Velde)
    
    changes from v20->v21: (Jes Sorensen review)
     * use qemu infrastructure: qemu-thread, qemu-common (qemu_malloc
      and qemu_free), error_report
     * assert instead of ASSERT
     * cosmetic fixes
     * use strpbrk and isspace
     * add --disable-nss --enable-nss here, instead of in the final patch.
     * split vscclient, passthru and docs to following patches.
    
    changes from v19->v20:
     * checkpatch.pl
    
    changes from v15->v16:
    
    Build:
     * don't erase self with distclean
     * fix make clean after make distclean
     * Makefile: make vscclient link quiet
    
    Behavioral:
     * vcard_emul_nss: load coolkey in more situations
     * vscclient:
      * use hton,ntoh
      * send init on connect, only start vevent thread on response
      * read payload after header check, before type switch
      * remove Reconnect
      * update for vscard_common changes, empty Flush implementation
    
    Style/Whitespace:
     * fix wrong variable usage
     * remove unused variable
     * use only C style comments
      * add copyright header
      * fix tabulation
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    libcacard: fix out of tree builds

diff --git a/Makefile b/Makefile
index 1e3f51a..fa93be5 100644
--- a/Makefile
+++ b/Makefile
@@ -141,6 +141,8 @@ check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
 check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
 check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
 
+QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
@@ -152,7 +154,7 @@ clean:
 	rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
 	rm -f trace-dtrace.h trace-dtrace.h-timestamp
 	$(MAKE) -C tests clean
-	for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
+	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
         done
@@ -163,7 +165,7 @@ distclean: clean
 	rm -f roms/seabios/config.mak roms/vgabios/config.mak
 	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
 	rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
-	for d in $(TARGET_DIRS) libhw32 libhw64 libuser libdis libdis-user; do \
+	for d in $(TARGET_DIRS) $(QEMULIBS); do \
 	rm -rf $$d || exit 1 ; \
         done
 
diff --git a/Makefile.objs b/Makefile.objs
index 07063f1..8c42524 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -352,6 +352,11 @@ user-obj-y += qemu-timer-common.o
 endif
 endif
 
+######################################################################
+# smartcard
+
+libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
+
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
diff --git a/Makefile.target b/Makefile.target
index 565e1fb..ace5608 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -358,6 +358,12 @@ obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
 
 endif # CONFIG_SOFTMMU
 
+ifndef CONFIG_LINUX_USER
+# libcacard needs qemu-thread support, and besides is only needed by devices
+# so not requires with linux-user targets
+obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
+endif # CONFIG_LINUX_USER
+
 obj-y += $(addprefix ../, $(trace-obj-y))
 obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
 
diff --git a/configure b/configure
index 01ee94d..2ef5c75 100755
--- a/configure
+++ b/configure
@@ -176,6 +176,7 @@ trace_file="trace"
 spice=""
 rbd=""
 smartcard=""
+smartcard_nss=""
 
 # parse CC options first
 for opt do
@@ -729,6 +730,10 @@ for opt do
   ;;
   --enable-smartcard) smartcard="yes"
   ;;
+  --disable-smartcard-nss) smartcard_nss="no"
+  ;;
+  --enable-smartcard-nss) smartcard_nss="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -928,6 +933,8 @@ echo "  --enable-spice           enable spice"
 echo "  --enable-rbd             enable building the rados block device (rbd)"
 echo "  --disable-smartcard      disable smartcard support"
 echo "  --enable-smartcard       enable smartcard support"
+echo "  --disable-smartcard-nss  disable smartcard nss support"
+echo "  --enable-smartcard-nss   enable smartcard nss support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2311,6 +2318,31 @@ EOF
   fi
 fi
 
+# check for libcacard for smartcard support
+if test "$smartcard" != "no" ; then
+    smartcard="yes"
+    smartcard_cflags=""
+    # TODO - what's the minimal nss version we support?
+    if test "$smartcard_nss" != "no"; then
+        if $pkg_config --atleast-version=3.12.8 nss >/dev/null 2>&1 ; then
+            smartcard_nss="yes"
+            smartcard_cflags="-I\$(SRC_PATH)/libcacard"
+            libcacard_libs=$($pkg_config --libs nss 2>/dev/null)
+            libcacard_cflags=$($pkg_config --cflags nss 2>/dev/null)
+            QEMU_CFLAGS="$QEMU_CFLAGS $smartcard_cflags $libcacard_cflags"
+            LIBS="$libcacard_libs $LIBS"
+        else
+            if test "$smartcard_nss" = "yes"; then
+                feature_not_found "nss"
+            fi
+            smartcard_nss="no"
+        fi
+    fi
+fi
+if test "$smartcard" = "no" ; then
+    smartcard_nss="no"
+fi
+
 ##########################################
 
 ##########################################
@@ -2549,6 +2581,7 @@ echo "Trace output file $trace_file-<pid>"
 echo "spice support     $spice"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
+echo "nss used          $smartcard_nss"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2835,6 +2868,10 @@ if test "$smartcard" = "yes" ; then
   echo "CONFIG_SMARTCARD=y" >> $config_host_mak
 fi
 
+if test "$smartcard_nss" = "yes" ; then
+  echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "CONFIG_BSD=y" >> $config_host_mak
@@ -3183,6 +3220,11 @@ fi
 if test "$target_darwin_user" = "yes" ; then
   echo "CONFIG_DARWIN_USER=y" >> $config_target_mak
 fi
+if test "$smartcard_nss" = "yes" ; then
+  echo "subdir-$target: subdir-libcacard" >> $config_host_mak
+  echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
+  echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
+fi
 list=""
 if test ! -z "$gdb_xml_files" ; then
   for x in $gdb_xml_files; do
@@ -3396,6 +3438,13 @@ for hwlib in 32 64; do
   echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
 done
 
+if [ "$source_path" != `pwd` ]; then
+    # out of tree build
+    mkdir -p libcacard
+    rm -f libcacard/Makefile
+    ln -s "$source_path/libcacard/Makefile" libcacard/Makefile
+fi
+
 d=libuser
 mkdir -p $d
 symlink $source_path/Makefile.user $d/Makefile
diff --git a/libcacard/Makefile b/libcacard/Makefile
new file mode 100644
index 0000000..0211eac
--- /dev/null
+++ b/libcacard/Makefile
@@ -0,0 +1,20 @@
+-include ../config-host.mak
+-include $(SRC_PATH)/Makefile.objs
+-include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/libcacard)
+
+ifeq ($(CONFIG_WIN32),y)
+QEMU_THREAD=qemu-thread-win32.o
+else
+QEMU_THREAD=qemu-thread-posix.o
+endif
+
+
+QEMU_OBJS=$(addprefix ../, $(QEMU_THREAD) $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o)
+
+QEMU_CFLAGS+=-I../
+
+clean:
+	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
+
diff --git a/libcacard/cac.c b/libcacard/cac.c
new file mode 100644
index 0000000..f34f63a
--- /dev/null
+++ b/libcacard/cac.c
@@ -0,0 +1,403 @@
+/*
+ * implement the applets for the CAC card.
+ *
+ * This code is licensed under the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+
+#include "cac.h"
+#include "vcard.h"
+#include "vcard_emul.h"
+#include "card_7816.h"
+
+#define CAC_GET_PROPERTIES  0x56
+#define CAC_GET_ACR         0x4c
+#define CAC_READ_BUFFER     0x52
+#define CAC_UPDATE_BUFFER   0x58
+#define CAC_SIGN_DECRYPT    0x42
+#define CAC_GET_CERTIFICATE 0x36
+
+/* private data for PKI applets */
+typedef struct CACPKIAppletDataStruct {
+    unsigned char *cert;
+    int cert_len;
+    unsigned char *cert_buffer;
+    int cert_buffer_len;
+    unsigned char *sign_buffer;
+    int sign_buffer_len;
+    VCardKey *key;
+} CACPKIAppletData;
+
+/*
+ * CAC applet private data
+ */
+struct VCardAppletPrivateStruct {
+    union {
+        CACPKIAppletData pki_data;
+        void *reserved;
+    } u;
+};
+
+/*
+ * handle all the APDU's that are common to all CAC applets
+ */
+static VCardStatus
+cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
+{
+    int ef;
+
+    switch (apdu->a_ins) {
+    case VCARD7816_INS_SELECT_FILE:
+        if (apdu->a_p1 != 0x02) {
+            /* let the 7816 code handle applet switches */
+            return VCARD_NEXT;
+        }
+        /* handle file id setting */
+        if (apdu->a_Lc != 2) {
+            *response = vcard_make_response(
+                VCARD7816_STATUS_ERROR_DATA_INVALID);
+            return VCARD_DONE;
+        }
+        /* CAC 1.0 only supports ef = 0 */
+        ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
+        if (ef != 0) {
+            *response = vcard_make_response(
+                VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
+            return VCARD_DONE;
+        }
+        *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
+        return VCARD_DONE;
+    case VCARD7816_INS_GET_RESPONSE:
+    case VCARD7816_INS_VERIFY:
+        /* let the 7816 code handle these */
+        return VCARD_NEXT;
+    case CAC_GET_PROPERTIES:
+    case CAC_GET_ACR:
+        /* skip these for now, this will probably be needed */
+        *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+        return VCARD_DONE;
+    }
+    *response = vcard_make_response(
+        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+    return VCARD_DONE;
+}
+
+/*
+ *  reset the inter call state between applet selects
+ */
+static VCardStatus
+cac_applet_pki_reset(VCard *card, int channel)
+{
+    VCardAppletPrivate *applet_private = NULL;
+    CACPKIAppletData *pki_applet = NULL;
+    applet_private = vcard_get_current_applet_private(card, channel);
+    assert(applet_private);
+    pki_applet = &(applet_private->u.pki_data);
+
+    pki_applet->cert_buffer = NULL;
+    if (pki_applet->sign_buffer) {
+        qemu_free(pki_applet->sign_buffer);
+        pki_applet->sign_buffer = NULL;
+    }
+    pki_applet->cert_buffer_len = 0;
+    pki_applet->sign_buffer_len = 0;
+    return VCARD_DONE;
+}
+
+static VCardStatus
+cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+                            VCardResponse **response)
+{
+    CACPKIAppletData *pki_applet = NULL;
+    VCardAppletPrivate *applet_private = NULL;
+    int size, next;
+    unsigned char *sign_buffer;
+    vcard_7816_status_t status;
+
+    applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
+    assert(applet_private);
+    pki_applet = &(applet_private->u.pki_data);
+
+    switch (apdu->a_ins) {
+    case CAC_UPDATE_BUFFER:
+        *response = vcard_make_response(
+            VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
+        return VCARD_DONE;
+    case CAC_GET_CERTIFICATE:
+        if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
+            *response = vcard_make_response(
+                             VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+            break;
+        }
+        assert(pki_applet->cert != NULL);
+        size = apdu->a_Le;
+        if (pki_applet->cert_buffer == NULL) {
+            pki_applet->cert_buffer = pki_applet->cert;
+            pki_applet->cert_buffer_len = pki_applet->cert_len;
+        }
+        size = MIN(size, pki_applet->cert_buffer_len);
+        next = MIN(255, pki_applet->cert_buffer_len - size);
+        *response = vcard_response_new_bytes(
+                        card, pki_applet->cert_buffer, size,
+                        apdu->a_Le, next ?
+                        VCARD7816_SW1_WARNING_CHANGE :
+                        VCARD7816_SW1_SUCCESS,
+                        next);
+        pki_applet->cert_buffer += size;
+        pki_applet->cert_buffer_len -= size;
+        if ((*response == NULL) || (next == 0)) {
+            pki_applet->cert_buffer = NULL;
+        }
+        if (*response == NULL) {
+            *response = vcard_make_response(
+                            VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+        }
+        return VCARD_DONE;
+    case CAC_SIGN_DECRYPT:
+        if (apdu->a_p2 != 0) {
+            *response = vcard_make_response(
+                             VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+            break;
+        }
+        size = apdu->a_Lc;
+
+        sign_buffer = realloc(pki_applet->sign_buffer,
+                      pki_applet->sign_buffer_len+size);
+        if (sign_buffer == NULL) {
+            qemu_free(pki_applet->sign_buffer);
+            pki_applet->sign_buffer = NULL;
+            pki_applet->sign_buffer_len = 0;
+            *response = vcard_make_response(
+                            VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+            return VCARD_DONE;
+        }
+        memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
+        size += pki_applet->sign_buffer_len;
+        switch (apdu->a_p1) {
+        case  0x80:
+            /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
+             * the rest */
+            pki_applet->sign_buffer = sign_buffer;
+            pki_applet->sign_buffer_len = size;
+            *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
+            return VCARD_DONE;
+        case 0x00:
+            /* we now have the whole buffer, do the operation, result will be
+             * in the sign_buffer */
+            status = vcard_emul_rsa_op(card, pki_applet->key,
+                                       sign_buffer, size);
+            if (status != VCARD7816_STATUS_SUCCESS) {
+                *response = vcard_make_response(status);
+                break;
+            }
+            *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
+                                                     VCARD7816_STATUS_SUCCESS);
+            if (*response == NULL) {
+                *response = vcard_make_response(
+                                VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+            }
+            break;
+        default:
+           *response = vcard_make_response(
+                                VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+            break;
+        }
+        qemu_free(sign_buffer);
+        pki_applet->sign_buffer = NULL;
+        pki_applet->sign_buffer_len = 0;
+        return VCARD_DONE;
+    case CAC_READ_BUFFER:
+        /* new CAC call, go ahead and use the old version for now */
+        /* TODO: implement */
+        *response = vcard_make_response(
+                                VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        return VCARD_DONE;
+    }
+    return cac_common_process_apdu(card, apdu, response);
+}
+
+
+static VCardStatus
+cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
+                           VCardResponse **response)
+{
+    switch (apdu->a_ins) {
+    case CAC_UPDATE_BUFFER:
+        *response = vcard_make_response(
+                        VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
+        return VCARD_DONE;
+    case CAC_READ_BUFFER:
+        /* new CAC call, go ahead and use the old version for now */
+        /* TODO: implement */
+        *response = vcard_make_response(
+                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        return VCARD_DONE;
+    }
+    return cac_common_process_apdu(card, apdu, response);
+}
+
+
+/*
+ * TODO: if we ever want to support general CAC middleware, we will need to
+ * implement the various containers.
+ */
+static VCardStatus
+cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
+                                  VCardResponse **response)
+{
+    switch (apdu->a_ins) {
+    case CAC_READ_BUFFER:
+    case CAC_UPDATE_BUFFER:
+        *response = vcard_make_response(
+                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        return VCARD_DONE;
+    default:
+        break;
+    }
+    return cac_common_process_apdu(card, apdu, response);
+}
+
+/*
+ * utilities for creating and destroying the private applet data
+ */
+static void
+cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
+{
+    CACPKIAppletData *pki_applet_data = NULL;
+    if (pki_applet_data == NULL) {
+        return;
+    }
+    pki_applet_data = &(applet_private->u.pki_data);
+    if (pki_applet_data->cert != NULL) {
+        qemu_free(pki_applet_data->cert);
+    }
+    if (pki_applet_data->sign_buffer != NULL) {
+        qemu_free(pki_applet_data->sign_buffer);
+    }
+    if (pki_applet_data->key != NULL) {
+        vcard_emul_delete_key(pki_applet_data->key);
+    }
+    qemu_free(applet_private);
+}
+
+static VCardAppletPrivate *
+cac_new_pki_applet_private(const unsigned char *cert,
+                           int cert_len, VCardKey *key)
+{
+    CACPKIAppletData *pki_applet_data = NULL;
+    VCardAppletPrivate *applet_private = NULL;
+    applet_private = (VCardAppletPrivate *)qemu_malloc(sizeof(VCardAppletPrivate));
+
+    pki_applet_data = &(applet_private->u.pki_data);
+    pki_applet_data->cert_buffer = NULL;
+    pki_applet_data->cert_buffer_len = 0;
+    pki_applet_data->sign_buffer = NULL;
+    pki_applet_data->sign_buffer_len = 0;
+    pki_applet_data->key = NULL;
+    pki_applet_data->cert = (unsigned char *)qemu_malloc(cert_len+1);
+    /*
+     * if we want to support compression, then we simply change the 0 to a 1
+     * and compress the cert data with libz
+     */
+    pki_applet_data->cert[0] = 0; /* not compressed */
+    memcpy(&pki_applet_data->cert[1], cert, cert_len);
+    pki_applet_data->cert_len = cert_len+1;
+
+    pki_applet_data->key = key;
+    return applet_private;
+}
+
+
+/*
+ * create a new cac applet which links to a given cert
+ */
+static VCardApplet *
+cac_new_pki_applet(int i, const unsigned char *cert,
+                   int cert_len, VCardKey *key)
+{
+    VCardAppletPrivate *applet_private = NULL;
+    VCardApplet *applet = NULL;
+    unsigned char pki_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
+    int pki_aid_len = sizeof(pki_aid);
+
+    pki_aid[pki_aid_len-1] = i;
+
+    applet_private = cac_new_pki_applet_private(cert, cert_len, key);
+    if (applet_private == NULL) {
+        goto failure;
+    }
+    applet = vcard_new_applet(cac_applet_pki_process_apdu, cac_applet_pki_reset,
+                              pki_aid, pki_aid_len);
+    if (applet == NULL) {
+        goto failure;
+    }
+    vcard_set_applet_private(applet, applet_private,
+                             cac_delete_pki_applet_private);
+    applet_private = NULL;
+
+    return applet;
+
+failure:
+    if (applet_private != NULL) {
+        cac_delete_pki_applet_private(applet_private);
+    }
+    return NULL;
+}
+
+
+static unsigned char cac_default_container_aid[] = {
+    0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
+static unsigned char cac_id_aid[] = {
+    0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 };
+/*
+ * Initialize the cac card. This is the only public function in this file. All
+ * the rest are connected through function pointers.
+ */
+VCardStatus
+cac_card_init(VReader *reader, VCard *card,
+              const char *params,
+              unsigned char * const *cert,
+              int cert_len[],
+              VCardKey *key[] /* adopt the keys*/,
+              int cert_count)
+{
+    int i;
+    VCardApplet *applet;
+
+    /* CAC Cards are VM Cards */
+    vcard_set_type(card, VCARD_VM);
+
+    /* create one PKI applet for each cert */
+    for (i = 0; i < cert_count; i++) {
+        applet = cac_new_pki_applet(i, cert[i], cert_len[i], key[i]);
+        if (applet == NULL) {
+            goto failure;
+        }
+        vcard_add_applet(card, applet);
+    }
+
+    /* create a default blank container applet */
+    applet = vcard_new_applet(cac_applet_container_process_apdu,
+                              NULL, cac_default_container_aid,
+                              sizeof(cac_default_container_aid));
+    if (applet == NULL) {
+        goto failure;
+    }
+    vcard_add_applet(card, applet);
+
+    /* create a default blank container applet */
+    applet = vcard_new_applet(cac_applet_id_process_apdu,
+                              NULL, cac_id_aid,
+                              sizeof(cac_id_aid));
+    if (applet == NULL) {
+        goto failure;
+    }
+    vcard_add_applet(card, applet);
+    return VCARD_DONE;
+
+failure:
+    return VCARD_FAIL;
+}
+
diff --git a/libcacard/cac.h b/libcacard/cac.h
new file mode 100644
index 0000000..15a61be
--- /dev/null
+++ b/libcacard/cac.h
@@ -0,0 +1,23 @@
+/*
+ * defines the entry point for the cac card. Only used by cac.c anc
+ * vcard_emul_type.c
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef CAC_H
+#define CAC_H 1
+#include "vcard.h"
+#include "vreader.h"
+/*
+ * Initialize the cac card. This is the only public function in this file. All
+ * the rest are connected through function pointers.
+ */
+VCardStatus cac_card_init(VReader *reader, VCard *card, const char *params,
+              unsigned char * const *cert, int cert_len[],
+              VCardKey *key[] /* adopt the keys*/,
+              int cert_count);
+
+/* not yet implemented */
+VCardStatus cac_is_cac_card(VReader *reader);
+#endif
diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c
new file mode 100644
index 0000000..eeea849
--- /dev/null
+++ b/libcacard/card_7816.c
@@ -0,0 +1,763 @@
+/*
+ * Implement the 7816 portion of the card spec
+ *
+ * This code is licensed under the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+
+#include "vcard.h"
+#include "vcard_emul.h"
+#include "card_7816.h"
+
+/*
+ * set the status bytes based on the status word
+ */
+static void
+vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
+{
+    unsigned char sw1, sw2;
+    response->b_status = status; /* make sure the status and swX representations
+                                  * are consistent */
+    sw1 = (status >> 8) & 0xff;
+    sw2 = status & 0xff;
+    response->b_sw1 = sw1;
+    response->b_sw2 = sw2;
+    response->b_data[response->b_len] = sw1;
+    response->b_data[response->b_len+1] = sw2;
+}
+
+/*
+ * set the status bytes in a response buffer
+ */
+static void
+vcard_response_set_status_bytes(VCardResponse *response,
+                               unsigned char sw1, unsigned char sw2)
+{
+    response->b_status = sw1 << 8 | sw2;
+    response->b_sw1 = sw1;
+    response->b_sw2 = sw2;
+    response->b_data[response->b_len] = sw1;
+    response->b_data[response->b_len+1] = sw2;
+}
+
+/*
+ * allocate a VCardResponse structure, plus space for the data buffer, and
+ * set up everything but the resonse bytes.
+ */
+VCardResponse *
+vcard_response_new_data(unsigned char *buf, int len)
+{
+    VCardResponse *new_response;
+
+    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
+    new_response->b_data = qemu_malloc(len + 2);
+    memcpy(new_response->b_data, buf, len);
+    new_response->b_total_len = len+2;
+    new_response->b_len = len;
+    new_response->b_type = VCARD_MALLOC;
+    return new_response;
+}
+
+static VCardResponse *
+vcard_init_buffer_response(VCard *card, unsigned char *buf, int len)
+{
+    VCardResponse *response;
+    VCardBufferResponse *buffer_response;
+
+    buffer_response = vcard_get_buffer_response(card);
+    if (buffer_response) {
+        vcard_set_buffer_response(card, NULL);
+        vcard_buffer_response_delete(buffer_response);
+    }
+    buffer_response = vcard_buffer_response_new(buf, len);
+    if (buffer_response == NULL) {
+        return NULL;
+    }
+    response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
+                                               len > 255 ? 0 : len);
+    if (response == NULL) {
+        return NULL;
+    }
+    vcard_set_buffer_response(card, buffer_response);
+    return response;
+}
+
+/*
+ * general buffer to hold results from APDU calls
+ */
+VCardResponse *
+vcard_response_new(VCard *card, unsigned char *buf,
+                   int len, int Le, vcard_7816_status_t status)
+{
+    VCardResponse *new_response;
+
+    if (len > Le) {
+        return vcard_init_buffer_response(card, buf, len);
+    }
+    new_response = vcard_response_new_data(buf, len);
+    if (new_response == NULL) {
+        return NULL;
+    }
+    vcard_response_set_status(new_response, status);
+    return new_response;
+}
+
+/*
+ * general buffer to hold results from APDU calls
+ */
+VCardResponse *
+vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
+                         unsigned char sw1, unsigned char sw2)
+{
+    VCardResponse *new_response;
+
+    if (len > Le) {
+        return vcard_init_buffer_response(card, buf, len);
+    }
+    new_response = vcard_response_new_data(buf, len);
+    if (new_response == NULL) {
+        return NULL;
+    }
+    vcard_response_set_status_bytes(new_response, sw1, sw2);
+    return new_response;
+}
+
+/*
+ * get a new Reponse buffer that only has a status.
+ */
+static VCardResponse *
+vcard_response_new_status(vcard_7816_status_t status)
+{
+    VCardResponse *new_response;
+
+    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
+    new_response->b_data = &new_response->b_sw1;
+    new_response->b_len = 0;
+    new_response->b_total_len = 2;
+    new_response->b_type = VCARD_MALLOC_STRUCT;
+    vcard_response_set_status(new_response, status);
+    return new_response;
+}
+
+/*
+ * same as above, but specify the status as separate bytes
+ */
+VCardResponse *
+vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
+{
+    VCardResponse *new_response;
+
+    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
+    new_response->b_data = &new_response->b_sw1;
+    new_response->b_len = 0;
+    new_response->b_total_len = 2;
+    new_response->b_type = VCARD_MALLOC_STRUCT;
+    vcard_response_set_status_bytes(new_response, sw1, sw2);
+    return new_response;
+}
+
+
+/*
+ * free the response buffer. The Buffer has a type to handle the buffer
+ * allocated in other ways than through malloc.
+ */
+void
+vcard_response_delete(VCardResponse *response)
+{
+    if (response == NULL) {
+        return;
+    }
+    switch (response->b_type) {
+    case VCARD_MALLOC:
+        /* everything was malloc'ed */
+        if (response->b_data) {
+            qemu_free(response->b_data);
+        }
+        qemu_free(response);
+        break;
+    case VCARD_MALLOC_DATA:
+        /* only the data buffer was malloc'ed */
+        if (response->b_data) {
+            qemu_free(response->b_data);
+        }
+        break;
+    case VCARD_MALLOC_STRUCT:
+        /* only the structure was malloc'ed */
+        qemu_free(response);
+        break;
+    case VCARD_STATIC:
+        break;
+    }
+}
+
+/*
+ * decode the class bit and set our generic type field, channel, and
+ * secure messaging values.
+ */
+static vcard_7816_status_t
+vcard_apdu_set_class(VCardAPDU *apdu) {
+    apdu->a_channel = 0;
+    apdu->a_secure_messaging = 0;
+    apdu->a_type = apdu->a_cla & 0xf0;
+    apdu->a_gen_type = VCARD_7816_ISO;
+
+    /* parse the class  tables 8 & 9 of the 7816-4 Part 4 spec */
+    switch (apdu->a_type) {
+        /* we only support the basic types */
+    case 0x00:
+    case 0x80:
+    case 0x90:
+    case 0xa0:
+        apdu->a_channel = apdu->a_cla & 3;
+        apdu->a_secure_messaging = apdu->a_cla & 0xe;
+        break;
+    case 0xb0:
+    case 0xc0:
+        break;
+
+    case 0x10:
+    case 0x20:
+    case 0x30:
+    case 0x40:
+    case 0x50:
+    case 0x60:
+    case 0x70:
+        /* Reserved for future use */
+        apdu->a_gen_type = VCARD_7816_RFU;
+        break;
+    case 0xd0:
+    case 0xe0:
+    case 0xf0:
+    default:
+        apdu->a_gen_type =
+            (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPIETARY;
+        break;
+    }
+    return VCARD7816_STATUS_SUCCESS;
+}
+
+/*
+ * set the Le and Lc fiels according to table 5 of the
+ * 7816-4 part 4 spec
+ */
+static vcard_7816_status_t
+vcard_apdu_set_length(VCardAPDU *apdu)
+{
+    int L, Le;
+
+    /* process according to table 5 of the 7816-4 Part 4 spec.
+     * variable names match the variables in the spec */
+    L = apdu->a_len-4; /* fixed APDU header */
+    apdu->a_Lc = 0;
+    apdu->a_Le = 0;
+    apdu->a_body = NULL;
+    switch (L) {
+    case 0:
+        /* 1 minimal apdu */
+        return VCARD7816_STATUS_SUCCESS;
+    case 1:
+        /* 2S only return values apdu */
+        /*   zero maps to 256 here */
+        apdu->a_Le = apdu->a_header->ah_Le ?
+                         apdu->a_header->ah_Le : 256;
+        return VCARD7816_STATUS_SUCCESS;
+    default:
+        /* if the ah_Le byte is zero and we have more than
+         * 1 byte in the header, then we must be using extended Le and Lc.
+         * process the extended now. */
+        if (apdu->a_header->ah_Le == 0) {
+            if (L < 3) {
+                /* coding error, need at least 3 bytes */
+                return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
+            }
+            /* calculate the first extended value. Could be either Le or Lc */
+            Le = (apdu->a_header->ah_body[0] << 8)
+               || apdu->a_header->ah_body[1];
+            if (L == 3) {
+                /* 2E extended, return data only */
+                /*   zero maps to 65536 */
+                apdu->a_Le = Le ? Le : 65536;
+                return VCARD7816_STATUS_SUCCESS;
+            }
+            if (Le == 0) {
+                /* reserved for future use, probably for next time we need
+                 * to extend the lengths */
+                return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
+            }
+            /* we know that the first extended value is Lc now */
+            apdu->a_Lc = Le;
+            apdu->a_body = &apdu->a_header->ah_body[2];
+            if (L == Le+3) {
+                /* 3E extended, only body parameters */
+                return VCARD7816_STATUS_SUCCESS;
+            }
+            if (L == Le+5) {
+                /* 4E extended, parameters and return data */
+                Le = (apdu->a_data[apdu->a_len-2] << 8)
+                   || apdu->a_data[apdu->a_len-1];
+                apdu->a_Le = Le ? Le : 65536;
+                return VCARD7816_STATUS_SUCCESS;
+            }
+            return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
+        }
+        /* not extended */
+        apdu->a_Lc = apdu->a_header->ah_Le;
+        apdu->a_body = &apdu->a_header->ah_body[0];
+        if (L ==  apdu->a_Lc + 1) {
+            /* 3S only body parameters */
+            return VCARD7816_STATUS_SUCCESS;
+        }
+        if (L ==  apdu->a_Lc + 2) {
+            /* 4S parameters and return data */
+            Le = apdu->a_data[apdu->a_len-1];
+            apdu->a_Le = Le ?  Le : 256;
+            return VCARD7816_STATUS_SUCCESS;
+        }
+        break;
+    }
+    return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
+}
+
+/*
+ * create a new APDU from a raw set of bytes. This will decode all the
+ * above fields. users of VCARDAPDU's can then depend on the already decoded
+ * values.
+ */
+VCardAPDU *
+vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
+{
+    VCardAPDU *new_apdu;
+
+    *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
+    if (len < 4) {
+        *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
+        return NULL;
+    }
+
+    new_apdu = (VCardAPDU *)qemu_malloc(sizeof(VCardAPDU));
+    new_apdu->a_data = qemu_malloc(len);
+    memcpy(new_apdu->a_data, raw_apdu, len);
+    new_apdu->a_len = len;
+    *status = vcard_apdu_set_class(new_apdu);
+    if (*status != VCARD7816_STATUS_SUCCESS) {
+        qemu_free(new_apdu);
+        return NULL;
+    }
+    *status = vcard_apdu_set_length(new_apdu);
+    if (*status != VCARD7816_STATUS_SUCCESS) {
+        qemu_free(new_apdu);
+        new_apdu = NULL;
+    }
+    return new_apdu;
+}
+
+void
+vcard_apdu_delete(VCardAPDU *apdu)
+{
+    if (apdu == NULL) {
+        return;
+    }
+    if (apdu->a_data) {
+        qemu_free(apdu->a_data);
+    }
+    qemu_free(apdu);
+}
+
+
+/*
+ * declare response buffers for all the 7816 defined error codes
+ */
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(
+                    VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
+VCARD_RESPONSE_NEW_STATIC_STATUS(
+                            VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
+VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
+
+/*
+ * return a single response code. This function cannot fail. It will always
+ * return a response.
+ */
+VCardResponse *
+vcard_make_response(vcard_7816_status_t status)
+{
+    VCardResponse *response = NULL;
+
+    switch (status) {
+    /* known 7816 response codes */
+    case VCARD7816_STATUS_SUCCESS:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_SUCCESS);
+    case VCARD7816_STATUS_WARNING:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING);
+    case VCARD7816_STATUS_WARNING_RET_CORUPT:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_RET_CORUPT);
+    case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
+    case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
+    case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
+    case VCARD7816_STATUS_WARNING_CHANGE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_CHANGE);
+    case VCARD7816_STATUS_WARNING_FILE_FILLED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_WARNING_FILE_FILLED);
+    case VCARD7816_STATUS_EXC_ERROR:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_EXC_ERROR);
+    case VCARD7816_STATUS_EXC_ERROR_CHANGE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_EXC_ERROR_CHANGE);
+    case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+    case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_WRONG_LENGTH);
+    case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
+    case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
+    case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
+    case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+    case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
+    case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
+    case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
+    case VCARD7816_STATUS_ERROR_DATA_INVALID:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_DATA_INVALID);
+    case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
+    case VCARD7816_STATUS_ERROR_DATA_NO_EF:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_DATA_NO_EF);
+    case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
+    case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
+    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
+    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
+    case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
+    case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
+    case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
+    case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
+    case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
+    case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+    case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
+    case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
+    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
+    case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
+    case VCARD7816_STATUS_ERROR_CLA_INVALID:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_CLA_INVALID);
+    case VCARD7816_STATUS_ERROR_GENERAL:
+        return VCARD_RESPONSE_GET_STATIC(
+                    VCARD7816_STATUS_ERROR_GENERAL);
+    default:
+        /* we don't know this status code, create a response buffer to
+         * hold it */
+        response = vcard_response_new_status(status);
+        if (response == NULL) {
+            /* couldn't allocate the buffer, return memmory error */
+            return VCARD_RESPONSE_GET_STATIC(
+                        VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+        }
+    }
+    assert(response);
+    return response;
+}
+
+/*
+ * Add File card support here if you need it.
+ */
+static VCardStatus
+vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
+                                   VCardResponse **response)
+{
+    /* TODO: if we want to support a virtual file system card, we do it here.
+     * It would probably be a pkcs #15 card type */
+    *response = vcard_make_response(
+                    VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+    return VCARD_DONE;
+}
+
+/*
+ * VM card (including java cards)
+ */
+static VCardStatus
+vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
+                          VCardResponse **response)
+{
+    int bytes_to_copy, next_byte_count, count;
+    VCardApplet *current_applet;
+    VCardBufferResponse *buffer_response;
+    vcard_7816_status_t status;
+
+    /* parse the class first */
+    if (apdu->a_gen_type !=  VCARD_7816_ISO) {
+        *response = vcard_make_response(
+                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        return VCARD_DONE;
+    }
+
+    /* use a switch so that if we need to support secure channel stuff later,
+     * we know where to put it */
+    switch (apdu->a_secure_messaging) {
+    case 0x0: /* no SM */
+        break;
+    case 0x4: /* proprietary SM */
+    case 0x8: /* header not authenticated */
+    case 0xc: /* header authenticated */
+    default:
+        /* for now, don't try to support secure channel stuff in the
+         * virtual card. */
+        *response = vcard_make_response(
+                        VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
+        return VCARD_DONE;
+    }
+
+    /* now parse the instruction */
+    switch (apdu->a_ins) {
+    case  VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
+    case  VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
+    case  VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
+    case  VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
+    case  VCARD7816_INS_ERASE_BINARY: /* applet control op */
+    case  VCARD7816_INS_READ_BINARY: /* applet control op */
+    case  VCARD7816_INS_WRITE_BINARY: /* applet control op */
+    case  VCARD7816_INS_UPDATE_BINARY: /* applet control op */
+    case  VCARD7816_INS_READ_RECORD: /* file op */
+    case  VCARD7816_INS_WRITE_RECORD: /* file op */
+    case  VCARD7816_INS_UPDATE_RECORD: /* file op */
+    case  VCARD7816_INS_APPEND_RECORD: /* file op */
+    case  VCARD7816_INS_ENVELOPE:
+    case  VCARD7816_INS_PUT_DATA:
+        *response = vcard_make_response(
+                            VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        break;
+
+    case  VCARD7816_INS_SELECT_FILE:
+        if (apdu->a_p1 != 0x04) {
+            *response = vcard_make_response(
+                            VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
+            break;
+        }
+
+        /* side effect, deselect the current applet if no applet has been found
+         * */
+        current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
+        vcard_select_applet(card, apdu->a_channel, current_applet);
+        if (current_applet) {
+            unsigned char *aid;
+            int aid_len;
+            aid = vcard_applet_get_aid(current_applet, &aid_len);
+            *response = vcard_response_new(card, aid, aid_len, apdu->a_Le,
+                                          VCARD7816_STATUS_SUCCESS);
+        } else {
+            *response = vcard_make_response(
+                             VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
+        }
+        break;
+
+    case  VCARD7816_INS_VERIFY:
+        if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
+            *response = vcard_make_response(
+                            VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
+        } else {
+            if (apdu->a_Lc == 0) {
+                /* handle pin count if possible */
+                count = vcard_emul_get_login_count(card);
+                if (count < 0) {
+                    *response = vcard_make_response(
+                                    VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
+                } else {
+                    if (count > 0xf) {
+                        count = 0xf;
+                    }
+                    *response = vcard_response_new_status_bytes(
+                                                VCARD7816_SW1_WARNING_CHANGE,
+                                                                0xc0 | count);
+                    if (*response == NULL) {
+                        *response = vcard_make_response(
+                                    VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+                    }
+                }
+            } else {
+                    status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
+                *response = vcard_make_response(status);
+            }
+        }
+        break;
+
+    case VCARD7816_INS_GET_RESPONSE:
+        buffer_response = vcard_get_buffer_response(card);
+        if (!buffer_response) {
+            *response = vcard_make_response(
+                            VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
+            /* handle error */
+            break;
+        }
+        bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
+        next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
+        *response = vcard_response_new_bytes(
+                        card, buffer_response->current, bytes_to_copy,
+                        apdu->a_Le,
+                        next_byte_count ?
+                        VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
+                        next_byte_count);
+        buffer_response->current += bytes_to_copy;
+        buffer_response->len -= bytes_to_copy;
+        if (*response == NULL || (next_byte_count == 0)) {
+            vcard_set_buffer_response(card, NULL);
+            vcard_buffer_response_delete(buffer_response);
+        }
+        if (*response == NULL) {
+            *response =
+                vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+        }
+        break;
+
+    case VCARD7816_INS_GET_DATA:
+        *response =
+            vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        break;
+
+    default:
+        *response =
+            vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        break;
+    }
+
+    /* response should have been set somewhere */
+    assert(*response != NULL);
+    return VCARD_DONE;
+}
+
+
+/*
+ * APDU processing starts here. This routes the card processing stuff to the
+ * right location.
+ */
+VCardStatus
+vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
+{
+    VCardStatus status;
+    VCardBufferResponse *buffer_response;
+
+    /* first handle any PTS commands, which aren't really APDU's */
+    if (apdu->a_type == VCARD_7816_PTS) {
+        /* the PTS responses aren't really responses either */
+        *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
+        /* PTS responses have no status bytes */
+        (*response)->b_total_len = (*response)->b_len;
+        return VCARD_DONE;
+    }
+    buffer_response = vcard_get_buffer_response(card);
+    if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
+        /* clear out buffer_response, return an error */
+        vcard_set_buffer_response(card, NULL);
+        vcard_buffer_response_delete(buffer_response);
+        *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR);
+        return VCARD_DONE;
+    }
+
+    status = vcard_process_applet_apdu(card, apdu, response);
+    if (status != VCARD_NEXT) {
+        return status;
+    }
+    switch (vcard_get_type(card)) {
+    case VCARD_FILE_SYSTEM:
+        return vcard7816_file_system_process_apdu(card, apdu, response);
+    case VCARD_VM:
+        return vcard7816_vm_process_apdu(card, apdu, response);
+    case VCARD_DIRECT:
+        /* if we are type direct, then the applet should handle everything */
+        assert("VCARD_DIRECT: applet failure");
+        break;
+    }
+    *response =
+        vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+    return VCARD_DONE;
+}
diff --git a/libcacard/card_7816.h b/libcacard/card_7816.h
new file mode 100644
index 0000000..2bb2a0d
--- /dev/null
+++ b/libcacard/card_7816.h
@@ -0,0 +1,62 @@
+/*
+ * Implement the 7816 portion of the card spec
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef CARD_7816_H
+#define CARD_7816_H  1
+
+#include "card_7816t.h"
+#include "vcardt.h"
+
+/*
+ * constructors for VCardResponse's
+ */
+/* response from a return buffer and a status */
+VCardResponse *vcard_response_new(VCard *card, unsigned char *buf, int len,
+                                  int Le, vcard_7816_status_t status);
+/* response from a return buffer and status bytes */
+VCardResponse *vcard_response_new_bytes(VCard *card, unsigned char *buf,
+                                        int len, int Le,
+                                        unsigned char sw1, unsigned char sw2);
+/* response from just status bytes */
+VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
+                                               unsigned char sw2);
+/* response from just status: NOTE this cannot fail, it will alwyas return a
+ * valid response, if it can't allocate memory, the response will be
+ * VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE */
+VCardResponse *vcard_make_response(vcard_7816_status_t status);
+
+/* create a raw response (status has already been encoded */
+VCardResponse *vcard_response_new_data(unsigned char *buf, int len);
+
+
+
+
+/*
+ * destructor for VCardResponse.
+ *  Can be called with a NULL response
+ */
+void vcard_response_delete(VCardResponse *response);
+
+/*
+ * constructor for VCardAPDU
+ */
+VCardAPDU *vcard_apdu_new(unsigned char *raw_apdu, int len,
+                          unsigned short *status);
+
+/*
+ * destructor for VCardAPDU
+ *  Can be called with a NULL apdu
+ */
+void vcard_apdu_delete(VCardAPDU *apdu);
+
+/*
+ * APDU processing starts here. This routes the card processing stuff to the
+ * right location. Always returns a valid response.
+ */
+VCardStatus vcard_process_apdu(VCard *card, VCardAPDU *apdu,
+                               VCardResponse **response);
+
+#endif
diff --git a/libcacard/card_7816t.h b/libcacard/card_7816t.h
new file mode 100644
index 0000000..9333285
--- /dev/null
+++ b/libcacard/card_7816t.h
@@ -0,0 +1,165 @@
+/*
+ * Implement the 7816 portion of the card spec
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef CARD_7816T_H
+#define CARD_7816T_H 1
+
+typedef unsigned short vcard_7816_status_t;
+
+struct VCardResponseStruct {
+    unsigned char *b_data;
+    vcard_7816_status_t b_status;
+    unsigned char b_sw1;
+    unsigned char b_sw2;
+    int b_len;
+    int b_total_len;
+    enum VCardResponseBufferType {
+        VCARD_MALLOC,
+        VCARD_MALLOC_DATA,
+        VCARD_MALLOC_STRUCT,
+        VCARD_STATIC
+    } b_type;
+};
+
+#define VCARD_RESPONSE_NEW_STATIC_STATUS(stat) \
+static const VCardResponse VCardResponse##stat = \
+        {(unsigned char *)&VCardResponse##stat.b_sw1, (stat), ((stat) >> 8), \
+         ((stat) & 0xff), 0, 2, VCARD_STATIC};
+
+#define VCARD_RESPONSE_NEW_STATIC_STATUS_BYTES(sw1, sw2) \
+static const VCardResponse VCARDResponse##sw1 = \
+        {(unsigned char *)&VCardResponse##name.b_sw1, ((sw1) << 8 | (sw2)), \
+         (sw1), (sw2), 0, 2, VCARD_STATIC};
+
+/* cast away the const, callers need may need to 'free' the
+ * result, and const implies that they don't */
+#define VCARD_RESPONSE_GET_STATIC(name) \
+        ((VCardResponse *)(&VCardResponse##name))
+
+typedef enum {
+    VCARD_7816_ISO,
+    VCARD_7816_RFU,
+    VCARD_7816_PTS,
+    VCARD_7816_PROPIETARY
+} VCardAPDUType;
+
+
+/*
+ * 7816 header. All APDU's have this header.
+ * They must be laid out in this order.
+ */
+struct VCardAPDUHeader {
+    unsigned char ah_cla;
+    unsigned char ah_ins;
+    unsigned char ah_p1;
+    unsigned char ah_p2;
+    unsigned char ah_Le;
+    unsigned char ah_body[1]; /* indefinate length */
+};
+
+/*
+ * 7816 APDU structure. The raw bytes are stored in the union and can be
+ * accessed directly through u.data (which is aliased as a_data).
+ *
+ * Names of the fields match the 7816 documentation.
+ */
+struct VCardAPDUStruct {
+    int a_len;                /* length of the whole buffer, including header */
+    int a_Lc;                 /* 7816 Lc (parameter length) value */
+    int a_Le;                 /* 7816 Le (expected result length) value */
+    unsigned char *a_body;    /* pointer to the parameter */
+    int a_channel;            /* decoded channel */
+    int a_secure_messaging;   /* decoded secure messaging type */
+    int a_type;               /* decoded type from cla (top nibble of class) */
+    VCardAPDUType a_gen_type; /* generic type (7816, PROPRIETARY, RFU, etc) */
+    union {
+        struct VCardAPDUHeader *header;
+        unsigned char   *data;
+    } u;
+/* give the subfields a unified look */
+#define a_header u.header
+#define a_data u.data
+#define a_cla a_header->ah_cla /* class */
+#define a_ins a_header->ah_ins /* instruction */
+#define a_p1 a_header->ah_p1   /* parameter 1 */
+#define a_p2 a_header->ah_p2   /* parameter 2 */
+};
+
+/* 7816 status codes */
+#define VCARD7816_STATUS_SUCCESS                              0x9000
+#define VCARD7816_STATUS_WARNING                              0x6200
+#define VCARD7816_STATUS_WARNING_RET_CORUPT                   0x6281
+#define VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE            0x6282
+#define VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED        0x6283
+#define VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID           0x6284
+#define VCARD7816_STATUS_WARNING_CHANGE                       0x6300
+#define VCARD7816_STATUS_WARNING_FILE_FILLED                  0x6381
+#define VCARD7816_STATUS_EXC_ERROR                            0x6400
+#define VCARD7816_STATUS_EXC_ERROR_CHANGE                     0x6500
+#define VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE             0x6581
+#define VCARD7816_STATUS_ERROR_WRONG_LENGTH                   0x6700
+#define VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED              0x6800
+#define VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED          0x6881
+#define VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED           0x6882
+#define VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED          0x6900
+#define VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE 0x6981
+#define VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED         0x6982
+#define VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED         0x6983
+#define VCARD7816_STATUS_ERROR_DATA_INVALID                   0x6984
+#define VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED        0x6985
+#define VCARD7816_STATUS_ERROR_DATA_NO_EF                     0x6986
+#define VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING              0x6987
+#define VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT            0x6988
+#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS               0x6a00
+#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA       0x6a80
+#define VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED         0x6a81
+#define VCARD7816_STATUS_ERROR_FILE_NOT_FOUND                 0x6a82
+#define VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND               0x6a83
+#define VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE              0x6a84
+#define VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT            0x6a85
+#define VCARD7816_STATUS_ERROR_P1_P2_INCORRECT                0x6a86
+#define VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT          0x6a87
+#define VCARD7816_STATUS_ERROR_DATA_NOT_FOUND                 0x6a88
+#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2             0x6b00
+#define VCARD7816_STATUS_ERROR_INS_CODE_INVALID               0x6d00
+#define VCARD7816_STATUS_ERROR_CLA_INVALID                    0x6e00
+#define VCARD7816_STATUS_ERROR_GENERAL                        0x6f00
+/* 7816 sw1 codes */
+#define VCARD7816_SW1_SUCCESS               0x90
+#define VCARD7816_SW1_RESPONSE_BYTES        0x61
+#define VCARD7816_SW1_WARNING               0x62
+#define VCARD7816_SW1_WARNING_CHANGE        0x63
+#define VCARD7816_SW1_EXC_ERROR             0x64
+#define VCARD7816_SW1_EXC_ERROR_CHANGE      0x65
+#define VCARD7816_SW1_ERROR_WRONG_LENGTH    0x67
+#define VCARD7816_SW1_CLA_ERROR             0x68
+#define VCARD7816_SW1_COMMAND_ERROR         0x69
+#define VCARD7816_SW1_P1_P2_ERROR           0x6a
+#define VCARD7816_SW1_LE_ERROR              0x6c
+#define VCARD7816_SW1_INS_ERROR             0x6d
+#define VCARD7816_SW1_CLA_NOT_SUPPORTED     0x6e
+
+/* 7816 Instructions */
+#define VCARD7816_INS_MANAGE_CHANNEL        0x70
+#define VCARD7816_INS_EXTERNAL_AUTHENTICATE 0x82
+#define VCARD7816_INS_GET_CHALLENGE         0x84
+#define VCARD7816_INS_INTERNAL_AUTHENTICATE 0x88
+#define VCARD7816_INS_ERASE_BINARY          0x0e
+#define VCARD7816_INS_READ_BINARY           0xb0
+#define VCARD7816_INS_WRITE_BINARY          0xd0
+#define VCARD7816_INS_UPDATE_BINARY         0xd6
+#define VCARD7816_INS_READ_RECORD           0xb2
+#define VCARD7816_INS_WRITE_RECORD          0xd2
+#define VCARD7816_INS_UPDATE_RECORD         0xdc
+#define VCARD7816_INS_APPEND_RECORD         0xe2
+#define VCARD7816_INS_ENVELOPE              0xc2
+#define VCARD7816_INS_PUT_DATA              0xda
+#define VCARD7816_INS_GET_DATA              0xca
+#define VCARD7816_INS_SELECT_FILE           0xa4
+#define VCARD7816_INS_VERIFY                0x20
+#define VCARD7816_INS_GET_RESPONSE          0xc0
+
+#endif
diff --git a/libcacard/event.c b/libcacard/event.c
new file mode 100644
index 0000000..bb2f921
--- /dev/null
+++ b/libcacard/event.c
@@ -0,0 +1,106 @@
+/*
+ * event queue implementation.
+ *
+ * This code is licensed under the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "qemu-thread.h"
+
+#include "vcard.h"
+#include "vreader.h"
+#include "vevent.h"
+
+VEvent *
+vevent_new(VEventType type, VReader *reader, VCard *card)
+{
+    VEvent *new_vevent;
+
+    new_vevent = (VEvent *)qemu_malloc(sizeof(VEvent));
+    new_vevent->next = NULL;
+    new_vevent->type = type;
+    new_vevent->reader = vreader_reference(reader);
+    new_vevent->card = vcard_reference(card);
+
+    return new_vevent;
+}
+
+void
+vevent_delete(VEvent *vevent)
+{
+    if (vevent == NULL) {
+        return;
+    }
+    vreader_free(vevent->reader);
+    vcard_free(vevent->card);
+    qemu_free(vevent);
+}
+
+/*
+ * VEvent queue management
+ */
+
+static VEvent *vevent_queue_head;
+static VEvent *vevent_queue_tail;
+static QemuMutex vevent_queue_lock;
+static QemuCond vevent_queue_condition;
+
+void vevent_queue_init(void)
+{
+    qemu_mutex_init(&vevent_queue_lock);
+    qemu_cond_init(&vevent_queue_condition);
+    vevent_queue_head = vevent_queue_tail = NULL;
+}
+
+void
+vevent_queue_vevent(VEvent *vevent)
+{
+    vevent->next = NULL;
+    qemu_mutex_lock(&vevent_queue_lock);
+    if (vevent_queue_head) {
+        assert(vevent_queue_tail);
+        vevent_queue_tail->next = vevent;
+    } else {
+        vevent_queue_head = vevent;
+    }
+    vevent_queue_tail = vevent;
+    qemu_cond_signal(&vevent_queue_condition);
+    qemu_mutex_unlock(&vevent_queue_lock);
+}
+
+/* must have lock */
+static VEvent *
+vevent_dequeue_vevent(void)
+{
+    VEvent *vevent = NULL;
+    if (vevent_queue_head) {
+        vevent = vevent_queue_head;
+        vevent_queue_head = vevent->next;
+        vevent->next = NULL;
+    }
+    return vevent;
+}
+
+VEvent *vevent_wait_next_vevent(void)
+{
+    VEvent *vevent;
+
+    qemu_mutex_lock(&vevent_queue_lock);
+    while ((vevent = vevent_dequeue_vevent()) == NULL) {
+        qemu_cond_wait(&vevent_queue_condition, &vevent_queue_lock);
+    }
+    qemu_mutex_unlock(&vevent_queue_lock);
+    return vevent;
+}
+
+VEvent *vevent_get_next_vevent(void)
+{
+    VEvent *vevent;
+
+    qemu_mutex_lock(&vevent_queue_lock);
+    vevent = vevent_dequeue_vevent();
+    qemu_mutex_unlock(&vevent_queue_lock);
+    return vevent;
+}
+
diff --git a/libcacard/eventt.h b/libcacard/eventt.h
new file mode 100644
index 0000000..0dc7bd4
--- /dev/null
+++ b/libcacard/eventt.h
@@ -0,0 +1,29 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef EVENTT_H
+#define EVENTT_H 1
+#include "vreadert.h"
+#include "vcardt.h"
+
+typedef struct VEventStruct VEvent;
+
+typedef enum {
+    VEVENT_READER_INSERT,
+    VEVENT_READER_REMOVE,
+    VEVENT_CARD_INSERT,
+    VEVENT_CARD_REMOVE,
+    VEVENT_LAST,
+} VEventType;
+
+struct VEventStruct {
+    VEvent *next;
+    VEventType type;
+    VReader *reader;
+    VCard *card;
+};
+#endif
+
+
diff --git a/libcacard/link_test.c b/libcacard/link_test.c
new file mode 100644
index 0000000..6f67a23
--- /dev/null
+++ b/libcacard/link_test.c
@@ -0,0 +1,22 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include "vcard.h"
+
+VCardStatus cac_card_init(const char *flags, VCard *card,
+                const unsigned char *cert[],
+                int cert_len[], VCardKey *key[] /* adopt the keys*/,
+                int cert_count);
+/*
+ * this will crash... just test the linkage right now
+ */
+
+main(int argc, char **argv)
+{
+    VCard *card; /* no constructor yet */
+    cac_card_init("", card, NULL, 0, NULL, 0);
+}
+
diff --git a/libcacard/vcard.c b/libcacard/vcard.c
new file mode 100644
index 0000000..29b4cce
--- /dev/null
+++ b/libcacard/vcard.c
@@ -0,0 +1,339 @@
+/*
+ * implement the Java card standard.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+
+#include "vcard.h"
+#include "vcard_emul.h"
+#include "card_7816t.h"
+
+struct VCardAppletStruct {
+    VCardApplet   *next;
+    VCardProcessAPDU process_apdu;
+    VCardResetApplet reset_applet;
+    unsigned char *aid;
+    int aid_len;
+    void *applet_private;
+    VCardAppletPrivateFree applet_private_free;
+};
+
+struct VCardStruct {
+    int reference_count;
+    VCardApplet *applet_list;
+    VCardApplet *current_applet[MAX_CHANNEL];
+    VCardBufferResponse *vcard_buffer_response;
+    VCardType type;
+    VCardEmul *vcard_private;
+    VCardEmulFree vcard_private_free;
+    VCardGetAtr vcard_get_atr;
+};
+
+VCardBufferResponse *
+vcard_buffer_response_new(unsigned char *buffer, int size)
+{
+    VCardBufferResponse *new_buffer;
+
+    new_buffer = (VCardBufferResponse *)qemu_malloc(sizeof(VCardBufferResponse));
+    new_buffer->buffer = (unsigned char *)qemu_malloc(size);
+    memcpy(new_buffer->buffer, buffer, size);
+    new_buffer->buffer_len = size;
+    new_buffer->current = new_buffer->buffer;
+    new_buffer->len = size;
+    return new_buffer;
+}
+
+void
+vcard_buffer_response_delete(VCardBufferResponse *buffer_response)
+{
+    if (buffer_response == NULL) {
+        return;
+    }
+    if (buffer_response->buffer) {
+        qemu_free(buffer_response->buffer);
+    }
+    qemu_free(buffer_response);
+}
+
+
+/*
+ * clean up state after a reset
+ */
+void
+vcard_reset(VCard *card, VCardPower power)
+{
+    int i;
+    VCardApplet *applet = NULL;
+
+    if (card->type ==  VCARD_DIRECT) {
+        /* select the last applet */
+        VCardApplet *current_applet = NULL;
+        for (current_applet = card->applet_list; current_applet;
+                                       current_applet = current_applet->next) {
+            applet = current_applet;
+        }
+    }
+    for (i = 0; i < MAX_CHANNEL; i++) {
+        card->current_applet[i] = applet;
+    }
+    if (card->vcard_buffer_response) {
+        vcard_buffer_response_delete(card->vcard_buffer_response);
+        card->vcard_buffer_response = NULL;
+    }
+    vcard_emul_reset(card, power);
+    if (applet) {
+        applet->reset_applet(card, 0);
+    }
+}
+
+/* applet utilities */
+
+/*
+ * applet utilities
+ */
+/* constructor */
+VCardApplet *
+vcard_new_applet(VCardProcessAPDU applet_process_function,
+                 VCardResetApplet applet_reset_function,
+                 unsigned char *aid, int aid_len)
+{
+    VCardApplet *applet;
+
+    applet = (VCardApplet *)qemu_malloc(sizeof(VCardApplet));
+    applet->next = NULL;
+    applet->applet_private = NULL;
+    applet->applet_private_free = NULL;
+    applet->process_apdu = applet_process_function;
+    applet->reset_applet = applet_reset_function;
+
+    applet->aid = qemu_malloc(aid_len);
+    memcpy(applet->aid, aid, aid_len);
+    applet->aid_len = aid_len;
+    return applet;
+}
+
+/* destructor */
+void
+vcard_delete_applet(VCardApplet *applet)
+{
+    if (applet == NULL) {
+        return;
+    }
+    if (applet->applet_private_free) {
+        applet->applet_private_free(applet->applet_private);
+        applet->applet_private = NULL;
+    }
+    if (applet->aid) {
+        qemu_free(applet->aid);
+        applet->aid = NULL;
+    }
+    qemu_free(applet);
+}
+
+/* accessor */
+void
+vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *private,
+                         VCardAppletPrivateFree private_free)
+{
+    if (applet->applet_private_free) {
+        applet->applet_private_free(applet->applet_private);
+    }
+    applet->applet_private = private;
+    applet->applet_private_free = private_free;
+}
+
+VCard *
+vcard_new(VCardEmul *private, VCardEmulFree private_free)
+{
+    VCard *new_card;
+    int i;
+
+    new_card = (VCard *)qemu_malloc(sizeof(VCard));
+    new_card->applet_list = NULL;
+    for (i = 0; i < MAX_CHANNEL; i++) {
+        new_card->current_applet[i] = NULL;
+    }
+    new_card->vcard_buffer_response = NULL;
+    new_card->type = VCARD_VM;
+    new_card->vcard_private = private;
+    new_card->vcard_private_free = private_free;
+    new_card->vcard_get_atr = NULL;
+    new_card->reference_count = 1;
+    return new_card;
+}
+
+VCard *
+vcard_reference(VCard *vcard)
+{
+    if (vcard == NULL) {
+        return NULL;
+    }
+    vcard->reference_count++;
+    return vcard;
+}
+
+void
+vcard_free(VCard *vcard)
+{
+    VCardApplet *current_applet = NULL;
+    VCardApplet *next_applet = NULL;
+
+    if (vcard == NULL) {
+        return;
+    }
+    vcard->reference_count--;
+    if (vcard->reference_count != 0) {
+        return;
+    }
+    if (vcard->vcard_private_free) {
+        (*vcard->vcard_private_free)(vcard->vcard_private);
+        vcard->vcard_private_free = 0;
+        vcard->vcard_private = 0;
+    }
+    for (current_applet = vcard->applet_list; current_applet;
+                                        current_applet = next_applet) {
+        next_applet = current_applet->next;
+        vcard_delete_applet(current_applet);
+    }
+    vcard_buffer_response_delete(vcard->vcard_buffer_response);
+    qemu_free(vcard);
+    return;
+}
+
+void
+vcard_get_atr(VCard *vcard, unsigned char *atr, int *atr_len)
+{
+    if (vcard->vcard_get_atr) {
+        (*vcard->vcard_get_atr)(vcard, atr, atr_len);
+        return;
+    }
+    vcard_emul_get_atr(vcard, atr, atr_len);
+}
+
+void
+vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr)
+{
+    card->vcard_get_atr = vcard_get_atr;
+}
+
+
+VCardStatus
+vcard_add_applet(VCard *card, VCardApplet *applet)
+{
+    applet->next = card->applet_list;
+    card->applet_list = applet;
+    /* if our card-type is direct, always call the applet */
+    if (card->type ==  VCARD_DIRECT) {
+        int i;
+
+        for (i = 0; i < MAX_CHANNEL; i++) {
+            card->current_applet[i] = applet;
+        }
+    }
+    return VCARD_DONE;
+}
+
+/*
+ * manage applets
+ */
+VCardApplet *
+vcard_find_applet(VCard *card, unsigned char *aid, int aid_len)
+{
+    VCardApplet *current_applet;
+
+    for (current_applet = card->applet_list; current_applet;
+                                        current_applet = current_applet->next) {
+        if (current_applet->aid_len != aid_len) {
+            continue;
+        }
+        if (memcmp(current_applet->aid, aid, aid_len) == 0) {
+            break;
+        }
+    }
+    return current_applet;
+}
+
+unsigned char *
+vcard_applet_get_aid(VCardApplet *applet, int *aid_len)
+{
+    if (applet == NULL) {
+        return NULL;
+    }
+    *aid_len = applet->aid_len;
+    return applet->aid;
+}
+
+
+void
+vcard_select_applet(VCard *card, int channel, VCardApplet *applet)
+{
+    assert(channel < MAX_CHANNEL);
+    card->current_applet[channel] = applet;
+    /* reset the applet */
+    if (applet && applet->reset_applet) {
+        applet->reset_applet(card, channel);
+    }
+}
+
+VCardAppletPrivate *
+vcard_get_current_applet_private(VCard *card, int channel)
+{
+    VCardApplet *applet = card->current_applet[channel];
+
+    if (applet == NULL) {
+        return NULL;
+    }
+    return applet->applet_private;
+}
+
+VCardStatus
+vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu,
+                          VCardResponse **response)
+{
+    if (card->current_applet[apdu->a_channel]) {
+        return card->current_applet[apdu->a_channel]->process_apdu(
+                                                        card, apdu, response);
+    }
+    return VCARD_NEXT;
+}
+
+/*
+ * Accessor functions
+ */
+/* accessor functions for the response buffer */
+VCardBufferResponse *
+vcard_get_buffer_response(VCard *card)
+{
+    return card->vcard_buffer_response;
+}
+
+void
+vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer)
+{
+    card->vcard_buffer_response = buffer;
+}
+
+
+/* accessor functions for the type */
+VCardType
+vcard_get_type(VCard *card)
+{
+    return card->type;
+}
+
+void
+vcard_set_type(VCard *card, VCardType type)
+{
+    card->type = type;
+}
+
+/* accessor for private data */
+VCardEmul *
+vcard_get_private(VCard *vcard)
+{
+    return vcard->vcard_private;
+}
+
diff --git a/libcacard/vcard.h b/libcacard/vcard.h
new file mode 100644
index 0000000..47dc703
--- /dev/null
+++ b/libcacard/vcard.h
@@ -0,0 +1,86 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef VCARD_H
+#define VCARD_H 1
+
+#include "vcardt.h"
+
+/*
+ * response buffer constructors and destructors.
+ *
+ * response buffers are used when we need to return more data than will fit in
+ * a normal APDU response (nominally 254 bytes).
+ */
+VCardBufferResponse *vcard_buffer_response_new(unsigned char *buffer, int size);
+void vcard_buffer_response_delete(VCardBufferResponse *buffer_response);
+
+
+/*
+ * clean up state on reset
+ */
+void vcard_reset(VCard *card, VCardPower power);
+
+/*
+ * applet utilities
+ */
+/*
+ * Constructor for a VCardApplet
+ */
+VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function,
+                              VCardResetApplet applet_reset_function,
+                              unsigned char *aid, int aid_len);
+
+/*
+ * destructor for a VCardApplet
+ *  Can be called with a NULL applet
+ */
+void vcard_delete_applet(VCardApplet *applet);
+
+/* accessor - set the card type specific private data */
+void vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *_private,
+                              VCardAppletPrivateFree private_free);
+
+/* set type of vcard */
+void vcard_set_type(VCard *card, VCardType type);
+
+/*
+ * utilities interacting with the current applet
+ */
+/* add a new applet to a card */
+VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
+/* find the applet on the card with the given aid */
+VCardApplet *vcard_find_applet(VCard *card, unsigned char *aid, int aid_len);
+/* set the following applet to be current on the given channel */
+void vcard_select_applet(VCard *card, int channel, VCardApplet *applet);
+/* get the card type specific private data on the given channel */
+VCardAppletPrivate *vcard_get_current_applet_private(VCard *card, int channel);
+/* fetch the applet's id */
+unsigned char *vcard_applet_get_aid(VCardApplet *applet, int *aid_len);
+
+/* process the apdu for the current selected applet/file */
+VCardStatus vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu,
+                                      VCardResponse **response);
+/*
+ * VCard utilities
+ */
+/* constructor */
+VCard *vcard_new(VCardEmul *_private, VCardEmulFree private_free);
+/* get a reference */
+VCard *vcard_reference(VCard *);
+/* destructor (reference counted) */
+void vcard_free(VCard *);
+/* get the atr from the card */
+void vcard_get_atr(VCard *card, unsigned char *atr, int *atr_len);
+void vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr);
+
+/* accessor functions for the response buffer */
+VCardBufferResponse *vcard_get_buffer_response(VCard *card);
+void vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer);
+/* accessor functions for the type */
+VCardType vcard_get_type(VCard *card);
+/* get the private data */
+VCardEmul *vcard_get_private(VCard *card);
+
+#endif
diff --git a/libcacard/vcard_emul.h b/libcacard/vcard_emul.h
new file mode 100644
index 0000000..963563f
--- /dev/null
+++ b/libcacard/vcard_emul.h
@@ -0,0 +1,65 @@
+/*
+ * This is the actual card emulator.
+ *
+ * These functions can be implemented in different ways on different platforms
+ * using the underlying system primitives. For Linux it uses NSS, though direct
+ * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
+ * used. On Windows CAPI could be used.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef VCARD_EMUL_H
+#define VCARD_EMUL_H 1
+
+#include "card_7816t.h"
+#include "vcard.h"
+#include "vcard_emul_type.h"
+
+/*
+ * types
+ */
+typedef enum {
+    VCARD_EMUL_OK = 0,
+    VCARD_EMUL_FAIL,
+    /* return values by vcard_emul_init */
+    VCARD_EMUL_INIT_ALREADY_INITED,
+} VCardEmulError;
+
+/* options are emul specific. call card_emul_parse_args to change a string
+ * To an options struct */
+typedef struct VCardEmulOptionsStruct VCardEmulOptions;
+
+/*
+ * Login functions
+ */
+/* return the number of login attempts still possible on the card. if unknown,
+ * return -1 */
+int vcard_emul_get_login_count(VCard *card);
+/* login into the card, return the 7816 status word (sw2 || sw1) */
+vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin,
+                                     int pin_len);
+
+/*
+ * key functions
+ */
+/* delete a key */
+void vcard_emul_delete_key(VCardKey *key);
+/* RSA sign/decrypt with the key, signature happens 'in place' */
+vcard_7816_status_t vcard_emul_rsa_op(VCard *card, VCardKey *key,
+                                  unsigned char *buffer, int buffer_size);
+
+void vcard_emul_reset(VCard *card, VCardPower power);
+void vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len);
+
+/* Re-insert of a card that has been removed by force removal */
+VCardEmulError vcard_emul_force_card_insert(VReader *vreader);
+/* Force a card removal even if the card is not physically removed */
+VCardEmulError vcard_emul_force_card_remove(VReader *vreader);
+
+VCardEmulOptions *vcard_emul_options(const char *args);
+VCardEmulError vcard_emul_init(const VCardEmulOptions *options);
+void vcard_emul_replay_insertion_events(void);
+void vcard_emul_usage(void);
+#endif
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
new file mode 100644
index 0000000..71f2ba3
--- /dev/null
+++ b/libcacard/vcard_emul_nss.c
@@ -0,0 +1,1157 @@
+/*
+ * This is the actual card emulator.
+ *
+ * These functions can be implemented in different ways on different platforms
+ * using the underlying system primitives. For Linux it uses NSS, though direct
+ * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
+ * used. On Windows CAPI could be used.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+/*
+ * NSS headers
+ */
+
+/* avoid including prototypes.h that redefines uint32 */
+#define NO_NSPR_10_SUPPORT
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <cert.h>
+#include <key.h>
+#include <secmod.h>
+#include <prthread.h>
+#include <secerr.h>
+
+#include "qemu-common.h"
+
+#include "vcard.h"
+#include "card_7816t.h"
+#include "vcard_emul.h"
+#include "vreader.h"
+#include "vevent.h"
+
+struct VCardKeyStruct {
+    CERTCertificate *cert;
+    PK11SlotInfo *slot;
+    SECKEYPrivateKey *key;
+};
+
+
+typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
+
+struct VReaderEmulStruct {
+    PK11SlotInfo *slot;
+    VCardEmulType default_type;
+    char *type_params;
+    PRBool present;
+    int     series;
+    VCard *saved_vcard;
+};
+
+/*
+ *  NSS Specific options
+ */
+struct VirtualReaderOptionsStruct {
+    char *name;
+    char *vname;
+    VCardEmulType card_type;
+    char *type_params;
+    char **cert_name;
+    int cert_count;
+};
+
+struct VCardEmulOptionsStruct {
+    void *nss_db;
+    VirtualReaderOptions *vreader;
+    int vreader_count;
+    VCardEmulType hw_card_type;
+    const char *hw_type_params;
+    PRBool use_hw;
+};
+
+static int nss_emul_init;
+
+/* if we have more that just the slot, define
+ * VCardEmulStruct here */
+
+/*
+ * allocate the set of arrays for certs, cert_len, key
+ */
+static PRBool
+vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
+                        VCardKey ***keysp, int cert_count)
+{
+    *certsp = NULL;
+    *cert_lenp = NULL;
+    *keysp = NULL;
+    *certsp = (unsigned char **)qemu_malloc(sizeof(unsigned char *)*cert_count);
+    *cert_lenp = (int *)qemu_malloc(sizeof(int)*cert_count);
+    *keysp = (VCardKey **)qemu_malloc(sizeof(VCardKey *)*cert_count);
+    return PR_TRUE;
+}
+
+/*
+ * Emulator specific card information
+ */
+typedef struct CardEmulCardStruct CardEmulPrivate;
+
+static VCardEmul *
+vcard_emul_new_card(PK11SlotInfo *slot)
+{
+    PK11_ReferenceSlot(slot);
+    /* currently we don't need anything other than the slot */
+    return (VCardEmul *)slot;
+}
+
+static void
+vcard_emul_delete_card(VCardEmul *vcard_emul)
+{
+    PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
+    if (slot == NULL) {
+        return;
+    }
+    PK11_FreeSlot(slot);
+}
+
+static PK11SlotInfo *
+vcard_emul_card_get_slot(VCard *card)
+{
+    /* note, the card is holding the reference, no need to get another one */
+    return (PK11SlotInfo *)vcard_get_private(card);
+}
+
+
+/*
+ * key functions
+ */
+/* private constructure */
+static VCardKey *
+vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
+{
+    VCardKey *key;
+
+    key = (VCardKey *)qemu_malloc(sizeof(VCardKey));
+    key->slot = PK11_ReferenceSlot(slot);
+    key->cert = CERT_DupCertificate(cert);
+    /* NOTE: if we aren't logged into the token, this could return NULL */
+    /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
+     * use the DER version of this function */
+    key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
+    return key;
+}
+
+/* destructor */
+void
+vcard_emul_delete_key(VCardKey *key)
+{
+    if (!nss_emul_init || (key == NULL)) {
+        return;
+    }
+    if (key->key) {
+        SECKEY_DestroyPrivateKey(key->key);
+        key->key = NULL;
+    }
+    if (key->cert) {
+        CERT_DestroyCertificate(key->cert);
+    }
+    if (key->slot) {
+        PK11_FreeSlot(key->slot);
+    }
+    return;
+}
+
+/*
+ * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
+ */
+static SECKEYPrivateKey *
+vcard_emul_get_nss_key(VCardKey *key)
+{
+    if (key->key) {
+        return key->key;
+    }
+    /* NOTE: if we aren't logged into the token, this could return NULL */
+    key->key = PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
+    return key->key;
+}
+
+/*
+ * Map NSS errors to 7816 errors
+ */
+static vcard_7816_status_t
+vcard_emul_map_error(int error)
+{
+    switch (error) {
+    case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
+        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+    case SEC_ERROR_BAD_DATA:
+    case SEC_ERROR_OUTPUT_LEN:
+    case SEC_ERROR_INPUT_LEN:
+    case SEC_ERROR_INVALID_ARGS:
+    case SEC_ERROR_INVALID_ALGORITHM:
+    case SEC_ERROR_NO_KEY:
+    case SEC_ERROR_INVALID_KEY:
+    case SEC_ERROR_DECRYPTION_DISALLOWED:
+        return VCARD7816_STATUS_ERROR_DATA_INVALID;
+    case SEC_ERROR_NO_MEMORY:
+        return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
+    }
+    return VCARD7816_STATUS_EXC_ERROR_CHANGE;
+}
+
+/* RSA sign/decrypt with the key, signature happens 'in place' */
+vcard_7816_status_t
+vcard_emul_rsa_op(VCard *card, VCardKey *key,
+                  unsigned char *buffer, int buffer_size)
+{
+    SECKEYPrivateKey *priv_key;
+    unsigned signature_len;
+    SECStatus rv;
+
+    if ((!nss_emul_init) || (key == NULL)) {
+        /* couldn't get the key, indicate that we aren't logged in */
+        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+    }
+    priv_key = vcard_emul_get_nss_key(key);
+
+    /*
+     * this is only true of the rsa signature
+     */
+    signature_len = PK11_SignatureLen(priv_key);
+    if (buffer_size != signature_len) {
+        return  VCARD7816_STATUS_ERROR_DATA_INVALID;
+    }
+    rv = PK11_PrivDecryptRaw(priv_key, buffer, &signature_len, signature_len,
+                             buffer, buffer_size);
+    if (rv != SECSuccess) {
+        return vcard_emul_map_error(PORT_GetError());
+    }
+    assert(buffer_size == signature_len);
+    return VCARD7816_STATUS_SUCCESS;
+}
+
+/*
+ * Login functions
+ */
+/* return the number of login attempts still possible on the card. if unknown,
+ * return -1 */
+int
+vcard_emul_get_login_count(VCard *card)
+{
+    return -1;
+}
+
+/* login into the card, return the 7816 status word (sw2 || sw1) */
+vcard_7816_status_t
+vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
+{
+    PK11SlotInfo *slot;
+    unsigned char *pin_string = NULL;
+    int i;
+    SECStatus rv;
+
+    if (!nss_emul_init) {
+        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+    }
+    slot = vcard_emul_card_get_slot(card);
+     /* We depend on the PKCS #11 module internal login state here because we
+      * create a separate process to handle each guest instance. If we needed
+      * to handle multiple guests from one process, then we would need to keep
+      * a lot of extra state in our card structure
+      * */
+    pin_string = qemu_malloc(pin_len+1);
+    memcpy(pin_string, pin, pin_len);
+    pin_string[pin_len] = 0;
+
+    /* handle CAC expanded pins correctly */
+    for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
+        pin_string[i] = 0;
+    }
+
+    rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
+    memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
+                                        to be snooped */
+    qemu_free(pin_string);
+    if (rv == SECSuccess) {
+        return VCARD7816_STATUS_SUCCESS;
+    }
+    /* map the error from port get error */
+    return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
+}
+
+void
+vcard_emul_reset(VCard *card, VCardPower power)
+{
+    PK11SlotInfo *slot;
+
+    if (!nss_emul_init) {
+        return;
+    }
+
+    /*
+     * if we reset the card (either power on or power off), we lose our login
+     * state
+     */
+    /* TODO: we may also need to send insertion/removal events? */
+    slot = vcard_emul_card_get_slot(card);
+    PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
+    return;
+}
+
+
+static VReader *
+vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
+{
+    VReaderList *reader_list = vreader_get_reader_list();
+    VReaderListEntry *current_entry = NULL;
+
+    if (reader_list == NULL) {
+        return NULL;
+    }
+    for (current_entry = vreader_list_get_first(reader_list); current_entry;
+                        current_entry = vreader_list_get_next(current_entry)) {
+        VReader *reader = vreader_list_get_reader(current_entry);
+        VReaderEmul *reader_emul = vreader_get_private(reader);
+        if (reader_emul->slot == slot) {
+            return reader;
+        }
+        vreader_free(reader);
+    }
+
+    return NULL;
+}
+
+/*
+ * create a new reader emul
+ */
+static VReaderEmul *
+vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
+{
+    VReaderEmul *new_reader_emul;
+
+    new_reader_emul = (VReaderEmul *)qemu_malloc(sizeof(VReaderEmul));
+
+    new_reader_emul->slot = PK11_ReferenceSlot(slot);
+    new_reader_emul->default_type = type;
+    new_reader_emul->type_params = strdup(params);
+    new_reader_emul->present = PR_FALSE;
+    new_reader_emul->series = 0;
+    new_reader_emul->saved_vcard = NULL;
+    return new_reader_emul;
+}
+
+static void
+vreader_emul_delete(VReaderEmul *vreader_emul)
+{
+    if (vreader_emul == NULL) {
+        return;
+    }
+    if (vreader_emul->slot) {
+        PK11_FreeSlot(vreader_emul->slot);
+    }
+    if (vreader_emul->type_params) {
+        qemu_free(vreader_emul->type_params);
+    }
+    qemu_free(vreader_emul);
+}
+
+/*
+ *  TODO: move this to emulater non-specific file
+ */
+static VCardEmulType
+vcard_emul_get_type(VReader *vreader)
+{
+    VReaderEmul *vreader_emul;
+
+    vreader_emul = vreader_get_private(vreader);
+    if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
+        return vreader_emul->default_type;
+    }
+
+    return vcard_emul_type_select(vreader);
+}
+/*
+ *  TODO: move this to emulater non-specific file
+ */
+static const char *
+vcard_emul_get_type_params(VReader *vreader)
+{
+    VReaderEmul *vreader_emul;
+
+    vreader_emul = vreader_get_private(vreader);
+    if (vreader_emul && vreader_emul->type_params) {
+        return vreader_emul->type_params;
+    }
+
+    return "";
+}
+
+/* pull the slot out of the reader private data */
+static PK11SlotInfo *
+vcard_emul_reader_get_slot(VReader *vreader)
+{
+    VReaderEmul *vreader_emul = vreader_get_private(vreader);
+    if (vreader_emul == NULL) {
+        return NULL;
+    }
+    return vreader_emul->slot;
+}
+
+/*
+ *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
+ *  historical bytes for any software emulated card. The remaining bytes can be
+ *  used to indicate the actual emulator
+ */
+static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
+
+void
+vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
+{
+    int len = MIN(sizeof(nss_atr), *atr_len);
+    assert(atr != NULL);
+
+    memcpy(atr, nss_atr, len);
+    *atr_len = len;
+    return;
+}
+
+/*
+ * create a new card from certs and keys
+ */
+static VCard *
+vcard_emul_make_card(VReader *reader,
+                     unsigned char * const *certs, int *cert_len,
+                     VCardKey *keys[], int cert_count)
+{
+    VCardEmul *vcard_emul;
+    VCard *vcard;
+    PK11SlotInfo *slot;
+    VCardEmulType type;
+    const char *params;
+
+    type = vcard_emul_get_type(reader);
+
+    /* ignore the inserted card */
+    if (type == VCARD_EMUL_NONE) {
+        return NULL;
+    }
+    slot = vcard_emul_reader_get_slot(reader);
+    if (slot == NULL) {
+        return NULL;
+    }
+
+    params = vcard_emul_get_type_params(reader);
+    /* params these can be NULL */
+
+    vcard_emul = vcard_emul_new_card(slot);
+    if (vcard_emul == NULL) {
+        return NULL;
+    }
+    vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
+    if (vcard == NULL) {
+        vcard_emul_delete_card(vcard_emul);
+        return NULL;
+    }
+    vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
+    return vcard;
+}
+
+
+/*
+ * 'clone' a physical card as a virtual card
+ */
+static VCard *
+vcard_emul_mirror_card(VReader *vreader)
+{
+    /*
+     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
+     * us the real certs until we log in.
+     */
+    PK11GenericObject *firstObj, *thisObj;
+    int cert_count;
+    unsigned char **certs;
+    int *cert_len;
+    VCardKey **keys;
+    PK11SlotInfo *slot;
+    PRBool ret;
+
+    slot = vcard_emul_reader_get_slot(vreader);
+    if (slot == NULL) {
+        return NULL;
+    }
+
+    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
+    if (firstObj == NULL) {
+        return NULL;
+    }
+
+    /* count the certs */
+    cert_count = 0;
+    for (thisObj = firstObj; thisObj;
+                             thisObj = PK11_GetNextGenericObject(thisObj)) {
+        cert_count++;
+    }
+
+    if (cert_count == 0) {
+        PK11_DestroyGenericObjects(firstObj);
+        return NULL;
+    }
+
+    /* allocate the arrays */
+    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
+    if (ret == PR_FALSE) {
+        return NULL;
+    }
+
+    /* fill in the arrays */
+    cert_count = 0;
+    for (thisObj = firstObj; thisObj;
+                             thisObj = PK11_GetNextGenericObject(thisObj)) {
+        SECItem derCert;
+        CERTCertificate *cert;
+        SECStatus rv;
+
+        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
+                                   CKA_VALUE, &derCert);
+        if (rv != SECSuccess) {
+            continue;
+        }
+        /* create floating temp cert. This gives us a cert structure even if
+         * the token isn't logged in */
+        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
+                                       NULL, PR_FALSE, PR_TRUE);
+        SECITEM_FreeItem(&derCert, PR_FALSE);
+        if (cert == NULL) {
+            continue;
+        }
+
+        certs[cert_count] = cert->derCert.data;
+        cert_len[cert_count] = cert->derCert.len;
+        keys[cert_count] = vcard_emul_make_key(slot, cert);
+        cert_count++;
+        CERT_DestroyCertificate(cert); /* key obj still has a reference */
+    }
+
+    /* now create the card */
+    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
+}
+
+static VCardEmulType default_card_type = VCARD_EMUL_NONE;
+static const char *default_type_params = "";
+
+/*
+ * This thread looks for card and reader insertions and puts events on the
+ * event queue
+ */
+static void
+vcard_emul_event_thread(void *arg)
+{
+    PK11SlotInfo *slot;
+    VReader *vreader;
+    VReaderEmul *vreader_emul;
+    VCard *vcard;
+    SECMODModule *module = (SECMODModule *)arg;
+
+    do {
+        slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
+        if (slot == NULL) {
+            break;
+        }
+        vreader = vcard_emul_find_vreader_from_slot(slot);
+        if (vreader == NULL) {
+            /* new vreader */
+            vreader_emul = vreader_emul_new(slot, default_card_type,
+                                            default_type_params);
+            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
+                                  vreader_emul_delete);
+            PK11_FreeSlot(slot);
+            slot = NULL;
+            vreader_add_reader(vreader);
+            vreader_free(vreader);
+            continue;
+        }
+        /* card remove/insert */
+        vreader_emul = vreader_get_private(vreader);
+        if (PK11_IsPresent(slot)) {
+            int series = PK11_GetSlotSeries(slot);
+            if (series != vreader_emul->series) {
+                if (vreader_emul->present) {
+                    vreader_insert_card(vreader, NULL);
+                }
+                vcard = vcard_emul_mirror_card(vreader);
+                vreader_insert_card(vreader, vcard);
+                vcard_free(vcard);
+            }
+            vreader_emul->series = series;
+            vreader_emul->present = 1;
+            vreader_free(vreader);
+            PK11_FreeSlot(slot);
+            continue;
+        }
+        if (vreader_emul->present) {
+            vreader_insert_card(vreader, NULL);
+        }
+        vreader_emul->series = 0;
+        vreader_emul->present = 0;
+        PK11_FreeSlot(slot);
+        vreader_free(vreader);
+    } while (1);
+}
+
+/* if the card is inserted when we start up, make sure our state is correct */
+static void
+vcard_emul_init_series(VReader *vreader, VCard *vcard)
+{
+    VReaderEmul *vreader_emul = vreader_get_private(vreader);
+    PK11SlotInfo *slot = vreader_emul->slot;
+
+    vreader_emul->present = PK11_IsPresent(slot);
+    vreader_emul->series = PK11_GetSlotSeries(slot);
+    if (vreader_emul->present == 0) {
+        vreader_insert_card(vreader, NULL);
+    }
+}
+
+/*
+ * each module has a separate wait call, create a thread for each module that
+ * we are using.
+ */
+static void
+vcard_emul_new_event_thread(SECMODModule *module)
+{
+    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
+                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
+                     PR_UNJOINABLE_THREAD, 0);
+}
+
+static const VCardEmulOptions default_options = {
+    .nss_db = NULL,
+    .vreader = NULL,
+    .vreader_count = 0,
+    .hw_card_type = VCARD_EMUL_CAC,
+    .hw_type_params = "",
+    .use_hw = PR_TRUE
+};
+
+
+/*
+ *  NSS needs the app to supply a password prompt. In our case the only time
+ *  the password is supplied is as part of the Login APDU. The actual password
+ *  is passed in the pw_arg in that case. In all other cases pw_arg should be
+ *  NULL.
+ */
+static char *
+vcard_emul_get_password(PK11SlotInfo *slot, PRBool retries, void *pw_arg)
+{
+    /* if it didn't work the first time, don't keep trying */
+    if (retries) {
+        return NULL;
+    }
+    /* we are looking up a password when we don't have one in hand */
+    if (pw_arg == NULL) {
+        return NULL;
+    }
+    /* TODO: we really should verify that were are using the right slot */
+    return PORT_Strdup(pw_arg);
+}
+
+/* Force a card removal even if the card is not physically removed */
+VCardEmulError
+vcard_emul_force_card_remove(VReader *vreader)
+{
+    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
+        return VCARD_EMUL_FAIL; /* card is already removed */
+    }
+
+    /* OK, remove it */
+    vreader_insert_card(vreader, NULL);
+    return VCARD_EMUL_OK;
+}
+
+/* Re-insert of a card that has been removed by force removal */
+VCardEmulError
+vcard_emul_force_card_insert(VReader *vreader)
+{
+    VReaderEmul *vreader_emul;
+    VCard *vcard;
+
+    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
+        return VCARD_EMUL_FAIL; /* card is already removed */
+    }
+    vreader_emul = vreader_get_private(vreader);
+
+    /* if it's a softcard, get the saved vcard from the reader emul structure */
+    if (vreader_emul->saved_vcard) {
+        vcard = vcard_reference(vreader_emul->saved_vcard);
+    } else {
+        /* it must be a physical card, rebuild it */
+        if (!PK11_IsPresent(vreader_emul->slot)) {
+            /* physical card has been removed, not way to reinsert it */
+            return VCARD_EMUL_FAIL;
+        }
+        vcard = vcard_emul_mirror_card(vreader);
+    }
+    vreader_insert_card(vreader, vcard);
+    vcard_free(vcard);
+
+    return VCARD_EMUL_OK;
+}
+
+
+static PRBool
+module_has_removable_hw_slots(SECMODModule *mod)
+{
+    int i;
+    PRBool ret = PR_FALSE;
+    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
+
+    if (!moduleLock) {
+        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+        return ret;
+    }
+    SECMOD_GetReadLock(moduleLock);
+    for (i = 0; i < mod->slotCount; i++) {
+        PK11SlotInfo *slot = mod->slots[i];
+        if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
+            ret = PR_TRUE;
+            break;
+        }
+    }
+    SECMOD_ReleaseReadLock(moduleLock);
+    return ret;
+}
+
+/* Previously we returned FAIL if no readers found. This makes
+ * no sense when using hardware, since there may be no readers connected
+ * at the time vcard_emul_init is called, but they will be properly
+ * recognized later. So Instead return FAIL only if no_hw==1 and no
+ * vcards can be created (indicates error with certificates provided
+ * or db), or if any other higher level error (NSS error, missing coolkey). */
+static int vcard_emul_init_called;
+
+VCardEmulError
+vcard_emul_init(const VCardEmulOptions *options)
+{
+    SECStatus rv;
+    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
+    VReader *vreader;
+    VReaderEmul *vreader_emul;
+    SECMODListLock *module_lock;
+    SECMODModuleList *module_list;
+    SECMODModuleList *mlp;
+    int i;
+
+    if (vcard_emul_init_called) {
+        return VCARD_EMUL_INIT_ALREADY_INITED;
+    }
+    vcard_emul_init_called = 1;
+    vreader_init();
+    vevent_queue_init();
+
+    if (options == NULL) {
+        options = &default_options;
+    }
+
+    /* first initialize NSS */
+    if (options->nss_db) {
+        rv = NSS_Init(options->nss_db);
+    } else {
+        rv = NSS_Init("sql:/etc/pki/nssdb");
+    }
+    if (rv != SECSuccess) {
+        return VCARD_EMUL_FAIL;
+    }
+    /* Set password callback function */
+    PK11_SetPasswordFunc(vcard_emul_get_password);
+
+    /* set up soft cards emulated by software certs rather than physical cards
+     * */
+    for (i = 0; i < options->vreader_count; i++) {
+        int j;
+        int cert_count;
+        unsigned char **certs;
+        int *cert_len;
+        VCardKey **keys;
+        PK11SlotInfo *slot;
+
+        slot = PK11_FindSlotByName(options->vreader[i].name);
+        if (slot == NULL) {
+            continue;
+        }
+        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
+                                        options->vreader[i].type_params);
+        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
+                              vreader_emul_delete);
+        vreader_add_reader(vreader);
+        cert_count = options->vreader[i].cert_count;
+
+        ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
+                                      options->vreader[i].cert_count);
+        if (ret == PR_FALSE) {
+            continue;
+        }
+        cert_count = 0;
+        for (j = 0; j < options->vreader[i].cert_count; j++) {
+            /* we should have a better way of identifying certs than by
+             * nickname here */
+            CERTCertificate *cert = PK11_FindCertFromNickname(
+                                        options->vreader[i].cert_name[j],
+                                        NULL);
+            if (cert == NULL) {
+                continue;
+            }
+            certs[cert_count] = cert->derCert.data;
+            cert_len[cert_count] = cert->derCert.len;
+            keys[cert_count] = vcard_emul_make_key(slot, cert);
+            /* this is safe because the key is still holding a cert reference */
+            CERT_DestroyCertificate(cert);
+            cert_count++;
+        }
+        if (cert_count) {
+            VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
+                                                keys, cert_count);
+            vreader_insert_card(vreader, vcard);
+            vcard_emul_init_series(vreader, vcard);
+            /* allow insertion and removal of soft cards */
+            vreader_emul->saved_vcard = vcard_reference(vcard);
+            vcard_free(vcard);
+            vreader_free(vreader);
+            has_readers = PR_TRUE;
+        }
+    }
+
+    /* if we aren't suppose to use hw, skip looking up hardware tokens */
+    if (!options->use_hw) {
+        nss_emul_init = has_readers;
+        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
+    }
+
+    /* make sure we have some PKCS #11 module loaded */
+    module_lock = SECMOD_GetDefaultModuleListLock();
+    module_list = SECMOD_GetDefaultModuleList();
+    need_coolkey_module = !has_readers;
+    SECMOD_GetReadLock(module_lock);
+    for (mlp = module_list; mlp; mlp = mlp->next) {
+        SECMODModule *module = mlp->module;
+        if (module_has_removable_hw_slots(module)) {
+            need_coolkey_module = PR_FALSE;
+            break;
+        }
+    }
+    SECMOD_ReleaseReadLock(module_lock);
+
+    if (need_coolkey_module) {
+        SECMODModule *module;
+        module = SECMOD_LoadUserModule(
+                    (char *)"library=libcoolkeypk11.so name=Coolkey",
+                    NULL, PR_FALSE);
+        if (module == NULL) {
+            return VCARD_EMUL_FAIL;
+        }
+        SECMOD_DestroyModule(module); /* free our reference, Module will still
+                                       * be on the list.
+                                       * until we destroy it */
+    }
+
+    /* now examine all the slots, finding which should be readers */
+    /* We should control this with options. For now we mirror out any
+     * removable hardware slot */
+    default_card_type = options->hw_card_type;
+    default_type_params = strdup(options->hw_type_params);
+
+    SECMOD_GetReadLock(module_lock);
+    for (mlp = module_list; mlp; mlp = mlp->next) {
+        SECMODModule *module = mlp->module;
+        PRBool has_emul_slots = PR_FALSE;
+
+        if (module == NULL) {
+                continue;
+        }
+
+        for (i = 0; i < module->slotCount; i++) {
+            PK11SlotInfo *slot = module->slots[i];
+
+            /* only map removable HW slots */
+            if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
+                continue;
+            }
+            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
+                                            options->hw_type_params);
+            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
+                                  vreader_emul_delete);
+            vreader_add_reader(vreader);
+
+            has_readers = PR_TRUE;
+            has_emul_slots = PR_TRUE;
+
+            if (PK11_IsPresent(slot)) {
+                VCard *vcard;
+                vcard = vcard_emul_mirror_card(vreader);
+                vreader_insert_card(vreader, vcard);
+                vcard_emul_init_series(vreader, vcard);
+                vcard_free(vcard);
+            }
+        }
+        if (has_emul_slots) {
+            vcard_emul_new_event_thread(module);
+        }
+    }
+    SECMOD_ReleaseReadLock(module_lock);
+    nss_emul_init = has_readers;
+
+    return VCARD_EMUL_OK;
+}
+
+/* Recreate card insert events for all readers (user should
+ * deduce implied reader insert. perhaps do a reader insert as well?)
+ */
+void
+vcard_emul_replay_insertion_events(void)
+{
+    VReaderListEntry *current_entry;
+    VReaderListEntry *next_entry = NULL;
+    VReaderList *list = vreader_get_reader_list();
+
+    for (current_entry = vreader_list_get_first(list); current_entry;
+            current_entry = next_entry) {
+        VReader *vreader = vreader_list_get_reader(current_entry);
+        next_entry = vreader_list_get_next(current_entry);
+        vreader_queue_card_event(vreader);
+    }
+}
+
+/*
+ *  Silly little functions to help parsing our argument string
+ */
+static char *
+copy_string(const char *str, int str_len)
+{
+    char *new_str;
+
+    new_str = qemu_malloc(str_len+1);
+    memcpy(new_str, str, str_len);
+    new_str[str_len] = 0;
+    return new_str;
+}
+
+static int
+count_tokens(const char *str, char token, char token_end)
+{
+    int count = 0;
+
+    for (; *str; str++) {
+        if (*str == token) {
+            count++;
+        }
+        if (*str == token_end) {
+            break;
+        }
+    }
+    return count;
+}
+
+static const char *
+strip(const char *str)
+{
+    for (; *str && !isspace(*str); str++) {
+    }
+    return str;
+}
+
+static const char *
+find_blank(const char *str)
+{
+    for (; *str && isspace(*str); str++) {
+    }
+    return str;
+}
+
+
+/*
+ *  We really want to use some existing argument parsing library here. That
+ *  would give us a consistant look */
+static VCardEmulOptions options;
+#define READER_STEP 4
+
+VCardEmulOptions *
+vcard_emul_options(const char *args)
+{
+    int reader_count = 0;
+    VCardEmulOptions *opts;
+    char type_str[100];
+    int type_len;
+
+    /* Allow the future use of allocating the options structure on the fly */
+    memcpy(&options, &default_options, sizeof(options));
+    opts = &options;
+
+    do {
+        args = strip(args); /* strip off the leading spaces */
+        if (*args == ',') {
+            continue;
+        }
+        /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
+         *       cert_2,cert_3...) */
+        if (strncmp(args, "soft=", 5) == 0) {
+            const char *name;
+            const char *vname;
+            const char *type_params;
+            VCardEmulType type;
+            int name_length, vname_length, type_params_length, count, i;
+            VirtualReaderOptions *vreaderOpt = NULL;
+
+            args = strip(args + 5);
+            if (*args != '(') {
+                continue;
+            }
+            name = args;
+            args = strpbrk(args + 1, ",)");
+            if (*args == 0) {
+                break;
+            }
+            if (*args == ')') {
+                args++;
+                continue;
+            }
+            args = strip(args+1);
+            name_length = args - name - 2;
+            vname = args;
+            args = strpbrk(args + 1, ",)");
+            if (*args == 0) {
+                break;
+            }
+            if (*args == ')') {
+                args++;
+                continue;
+            }
+            vname_length = args - name - 2;
+            args = strip(args+1);
+            type_len = strpbrk(args, ",)") - args;
+            assert(sizeof(type_str) > type_len);
+            strncpy(type_str, args, type_len);
+            type_str[type_len] = 0;
+            type = vcard_emul_type_from_string(type_str);
+            args = strpbrk(args, ",)");
+            if (*args == 0) {
+                break;
+            }
+            if (*args == ')') {
+                args++;
+                continue;
+            }
+            args = strip(args++);
+            type_params = args;
+            args = strpbrk(args + 1, ",)");
+            if (*args == 0) {
+                break;
+            }
+            if (*args == ')') {
+                args++;
+                continue;
+            }
+            type_params_length = args - name;
+            args = strip(args++);
+            if (*args == 0) {
+                break;
+            }
+
+            if (opts->vreader_count >= reader_count) {
+                reader_count += READER_STEP;
+                vreaderOpt = realloc(opts->vreader,
+                                reader_count * sizeof(*vreaderOpt));
+                if (vreaderOpt == NULL) {
+                    return opts; /* we're done */
+                }
+            }
+            opts->vreader = vreaderOpt;
+            vreaderOpt = &vreaderOpt[opts->vreader_count];
+            vreaderOpt->name = copy_string(name, name_length);
+            vreaderOpt->vname = copy_string(vname, vname_length);
+            vreaderOpt->card_type = type;
+            vreaderOpt->type_params =
+                copy_string(type_params, type_params_length);
+            count = count_tokens(args, ',', ')');
+            vreaderOpt->cert_count = count;
+            vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
+            for (i = 0; i < count; i++) {
+                const char *cert = args + 1;
+                args = strpbrk(args + 1, ",)");
+                vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
+            }
+            if (*args == ')') {
+                args++;
+            }
+            opts->vreader_count++;
+        /* use_hw= */
+        } else if (strncmp(args, "use_hw=", 7) == 0) {
+            args = strip(args+7);
+            if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
+                opts->use_hw = PR_FALSE;
+            } else {
+                opts->use_hw = PR_TRUE;
+            }
+            args = find_blank(args);
+        /* hw_type= */
+        } else if (strncmp(args, "hw_type=", 8) == 0) {
+            args = strip(args+8);
+            opts->hw_card_type = vcard_emul_type_from_string(args);
+            args = find_blank(args);
+        /* hw_params= */
+        } else if (strncmp(args, "hw_params=", 10) == 0) {
+            const char *params;
+            args = strip(args+10);
+            params = args;
+            args = find_blank(args);
+            opts->hw_type_params = copy_string(params, args-params);
+        /* db="/data/base/path" */
+        } else if (strncmp(args, "db=", 3) == 0) {
+            const char *db;
+            args = strip(args+3);
+            if (*args != '"') {
+                continue;
+            }
+            args++;
+            db = args;
+            args = strpbrk(args, "\"\n");
+            opts->nss_db = copy_string(db, args-db);
+            if (*args != 0) {
+                args++;
+            }
+        } else {
+            args = find_blank(args);
+        }
+    } while (*args != 0);
+
+    return opts;
+}
+
+void
+vcard_emul_usage(void)
+{
+   fprintf(stderr,
+"emul args: comma separated list of the following arguments\n"
+" db={nss_database}               (default sql:/etc/pki/nssdb)\n"
+" use_hw=[yes|no]                 (default yes)\n"
+" hw_type={card_type_to_emulate}  (default CAC)\n"
+" hw_param={param_for_card}       (default \"\")\n"
+" soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
+"       {cert1},{cert2},{cert3}    (default none)\n"
+"\n"
+"  {nss_database}          The location of the NSS cert & key database\n"
+"  {card_type_to_emulate}  What card interface to present to the guest\n"
+"  {param_for_card}        Card interface specific parameters\n"
+"  {slot_name}             NSS slot that contains the certs\n"
+"  {vreader_name}          Virutal reader name to present to the guest\n"
+"  {certN}                 Nickname of the certificate n on the virtual card\n"
+"\n"
+"These parameters come as a single string separated by blanks or newlines."
+"\n"
+"Unless use_hw is set to no, all tokens that look like removable hardware\n"
+"tokens will be presented to the guest using the emulator specified by\n"
+"hw_type, and parameters of hw_param.\n"
+"\n"
+"If more one or more soft= parameters are specified, these readers will be\n"
+"presented to the guest\n");
+}
diff --git a/libcacard/vcard_emul_type.c b/libcacard/vcard_emul_type.c
new file mode 100644
index 0000000..59a1458
--- /dev/null
+++ b/libcacard/vcard_emul_type.c
@@ -0,0 +1,57 @@
+/*
+ *  This file contains utility functions which abstract the different card
+ *  types.  The goal is that new card types can easily be added by simply
+ *  changing this file and vcard_emul_type.h. It is currently not a requirement
+ *  to dynamically add new card types.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <strings.h>
+#include "vcardt.h"
+#include "vcard_emul_type.h"
+#include "cac.h"
+
+VCardStatus vcard_init(VReader *vreader, VCard *vcard,
+                       VCardEmulType type, const char *params,
+                       unsigned char *const *cert, int cert_len[],
+                       VCardKey *key[], int cert_count)
+{
+    switch (type) {
+    case VCARD_EMUL_NONE:
+        break;
+    case VCARD_EMUL_CAC:
+        return cac_card_init(vreader, vcard, params,
+                             cert, cert_len, key,  cert_count);
+    /* add new ones here */
+    default:
+        break;
+    }
+    return VCARD_FAIL;
+}
+
+VCardEmulType vcard_emul_type_select(VReader *vreader)
+{
+#ifdef notdef
+    /* since there is only one emulator no need to call this function */
+    if (cac_is_cac_card(vreader) == VCARD_DONE) {
+        return VCARD_EMUL_CAC;
+    }
+#endif
+    /* return the default */
+    return VCARD_EMUL_CAC;
+}
+
+VCardEmulType vcard_emul_type_from_string(const char *type_string)
+{
+     if (strcasecmp(type_string, "CAC") == 0) {
+        return VCARD_EMUL_CAC;
+     }
+#ifdef USE_PASSTHRU
+     if (strcasecmp(type_string, "PASSTHRU") == 0) {
+        return VCARD_EMUL_PASSTHRU;
+     }
+#endif
+     return VCARD_EMUL_NONE;
+}
diff --git a/libcacard/vcard_emul_type.h b/libcacard/vcard_emul_type.h
new file mode 100644
index 0000000..0242f40
--- /dev/null
+++ b/libcacard/vcard_emul_type.h
@@ -0,0 +1,32 @@
+/*
+ *  This header file abstracts the different card types. The goal is new card
+ *  types can easily be added by simply changing this file and
+ *  vcard_emul_type.c. It is currently not a requirement to dynamically add new
+ *  card types.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef VCARD_EMUL_TYPE_H
+#define VCARD_EMUL_TYPE_H 1
+#include "vcardt.h"
+#include "vreadert.h"
+
+/*
+ * types
+ */
+typedef enum {
+     VCARD_EMUL_NONE = 0,
+     VCARD_EMUL_CAC,
+     VCARD_EMUL_PASSTHRU
+} VCardEmulType;
+
+/* functions used by the rest of the emulator */
+VCardStatus vcard_init(VReader *vreader, VCard *vcard, VCardEmulType type,
+                       const char *params, unsigned char * const *cert,
+                       int cert_len[], VCardKey *key[], int cert_count);
+VCardEmulType vcard_emul_type_select(VReader *vreader);
+VCardEmulType vcard_emul_type_from_string(const char *type_string);
+
+#endif
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
new file mode 100644
index 0000000..538bdde
--- /dev/null
+++ b/libcacard/vcardt.h
@@ -0,0 +1,64 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef VCARDT_H
+#define VCARDT_H 1
+
+/*
+ * these should come from some common spice header file
+ */
+#include <assert.h>
+#ifndef MIN
+#define MIN(x, y) ((x) > (y) ? (y) : (x))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+typedef struct VCardStruct VCard;
+typedef struct VCardAPDUStruct VCardAPDU;
+typedef struct VCardResponseStruct VCardResponse;
+typedef struct VCardBufferResponseStruct VCardBufferResponse;
+typedef struct VCardAppletStruct VCardApplet;
+typedef struct VCardAppletPrivateStruct VCardAppletPrivate;
+typedef struct VCardKeyStruct VCardKey;  /* opaque */
+typedef struct VCardEmulStruct VCardEmul;
+
+#define MAX_CHANNEL 4
+
+/* create an ATR with appropriate historical bytes */
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
+                               'V', 'C', 'A', 'R', 'D', '_'
+
+
+typedef enum {
+    VCARD_DONE,
+    VCARD_NEXT,
+    VCARD_FAIL
+} VCardStatus;
+
+typedef enum {
+    VCARD_FILE_SYSTEM,
+    VCARD_VM,
+    VCARD_DIRECT
+} VCardType;
+
+typedef enum {
+    VCARD_POWER_ON,
+    VCARD_POWER_OFF
+} VCardPower;
+
+typedef VCardStatus (*VCardProcessAPDU)(VCard *card, VCardAPDU *apdu,
+                                        VCardResponse **response);
+typedef VCardStatus (*VCardResetApplet)(VCard *card, int channel);
+typedef void (*VCardAppletPrivateFree) (VCardAppletPrivate *);
+typedef void (*VCardEmulFree) (VCardEmul *);
+typedef void (*VCardGetAtr) (VCard *, unsigned char *atr, int *atr_len);
+
+struct VCardBufferResponseStruct {
+    unsigned char *buffer;
+    int buffer_len;
+    unsigned char *current;
+    int len;
+};
+
+#endif
diff --git a/libcacard/vevent.h b/libcacard/vevent.h
new file mode 100644
index 0000000..38c3482
--- /dev/null
+++ b/libcacard/vevent.h
@@ -0,0 +1,27 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef EVENT_H
+#define EVENT_H 1
+#include "eventt.h"
+#include "vreadert.h"
+#include "vcardt.h"
+
+VEvent *vevent_new(VEventType type, VReader *reader, VCard *card);
+void vevent_delete(VEvent *);
+
+/*
+ * VEvent queueing services
+ */
+void vevent_queue_vevent(VEvent *);
+void vevent_queue_init(void);
+
+/*
+ *  VEvent dequeing services
+ */
+VEvent *vevent_wait_next_vevent(void);
+VEvent *vevent_get_next_vevent(void);
+
+
+#endif
diff --git a/libcacard/vreader.c b/libcacard/vreader.c
new file mode 100644
index 0000000..4a0125b
--- /dev/null
+++ b/libcacard/vreader.c
@@ -0,0 +1,513 @@
+/*
+ * emulate the reader
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "qemu-thread.h"
+
+#include "vcard.h"
+#include "vcard_emul.h"
+#include "card_7816.h"
+#include "vreader.h"
+#include "vevent.h"
+
+struct VReaderStruct {
+    int    reference_count;
+    VCard *card;
+    char *name;
+    vreader_id_t id;
+    QemuMutex lock;
+    VReaderEmul  *reader_private;
+    VReaderEmulFree reader_private_free;
+};
+
+/* manage locking */
+static inline void
+vreader_lock(VReader *reader)
+{
+    qemu_mutex_lock(&reader->lock);
+}
+
+static inline void
+vreader_unlock(VReader *reader)
+{
+    qemu_mutex_unlock(&reader->lock);
+}
+
+/*
+ * vreader constructor
+ */
+VReader *
+vreader_new(const char *name, VReaderEmul *private,
+            VReaderEmulFree private_free)
+{
+    VReader *reader;
+
+    reader = (VReader *)qemu_malloc(sizeof(VReader));
+    qemu_mutex_init(&reader->lock);
+    reader->reference_count = 1;
+    reader->name = name ? strdup(name) : NULL;
+    reader->card = NULL;
+    reader->id = (vreader_id_t)-1;
+    reader->reader_private = private;
+    reader->reader_private_free = private_free;
+    return reader;
+}
+
+/* get a reference */
+VReader*
+vreader_reference(VReader *reader)
+{
+    if (reader == NULL) {
+        return NULL;
+    }
+    vreader_lock(reader);
+    reader->reference_count++;
+    vreader_unlock(reader);
+    return reader;
+}
+
+/* free a reference */
+void
+vreader_free(VReader *reader)
+{
+    if (reader == NULL) {
+        return;
+    }
+    vreader_lock(reader);
+    if (reader->reference_count-- > 1) {
+        vreader_unlock(reader);
+        return;
+    }
+    vreader_unlock(reader);
+    if (reader->card) {
+        vcard_free(reader->card);
+    }
+    if (reader->name) {
+        qemu_free(reader->name);
+    }
+    if (reader->reader_private_free) {
+        reader->reader_private_free(reader->reader_private);
+    }
+    qemu_free(reader);
+    return;
+}
+
+static VCard *
+vreader_get_card(VReader *reader)
+{
+    VCard *card;
+
+    vreader_lock(reader);
+    card = vcard_reference(reader->card);
+    vreader_unlock(reader);
+    return card;
+}
+
+VReaderStatus
+vreader_card_is_present(VReader *reader)
+{
+    VCard *card = vreader_get_card(reader);
+
+    if (card == NULL) {
+        return VREADER_NO_CARD;
+    }
+    vcard_free(card);
+    return VREADER_OK;
+}
+
+vreader_id_t
+vreader_get_id(VReader *reader)
+{
+    if (reader == NULL) {
+        return (vreader_id_t)-1;
+    }
+    return reader->id;
+}
+
+VReaderStatus
+vreader_set_id(VReader *reader, vreader_id_t id)
+{
+    if (reader == NULL) {
+        return VREADER_NO_CARD;
+    }
+    reader->id = id;
+    return VREADER_OK;
+}
+
+const char *
+vreader_get_name(VReader *reader)
+{
+    if (reader == NULL) {
+        return NULL;
+    }
+    return reader->name;
+}
+
+VReaderEmul *
+vreader_get_private(VReader *reader)
+{
+    return reader->reader_private;
+}
+
+static VReaderStatus
+vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
+{
+    VCard *card = vreader_get_card(reader);
+
+    if (card == NULL) {
+        return VREADER_NO_CARD;
+    }
+    /*
+     * clean up our state
+     */
+    vcard_reset(card, power);
+    if (atr) {
+        vcard_get_atr(card, atr, len);
+    }
+    vcard_free(card); /* free our reference */
+    return VREADER_OK;
+}
+
+VReaderStatus
+vreader_power_on(VReader *reader, unsigned char *atr, int *len)
+{
+    return vreader_reset(reader, VCARD_POWER_ON, atr, len);
+}
+
+VReaderStatus
+vreader_power_off(VReader *reader)
+{
+    return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
+}
+
+
+VReaderStatus
+vreader_xfr_bytes(VReader *reader,
+                  unsigned char *send_buf, int send_buf_len,
+                  unsigned char *receive_buf, int *receive_buf_len)
+{
+    VCardAPDU *apdu;
+    VCardResponse *response = NULL;
+    VCardStatus card_status;
+    unsigned short status;
+    VCard *card = vreader_get_card(reader);
+
+    if (card == NULL) {
+        return VREADER_NO_CARD;
+    }
+
+    apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
+    if (apdu == NULL) {
+        response = vcard_make_response(status);
+        card_status = VCARD_DONE;
+    } else {
+        card_status = vcard_process_apdu(card, apdu, &response);
+    }
+    assert(card_status == VCARD_DONE);
+    if (card_status == VCARD_DONE) {
+        int size = MIN(*receive_buf_len, response->b_total_len);
+        memcpy(receive_buf, response->b_data, size);
+        *receive_buf_len = size;
+    }
+    vcard_response_delete(response);
+    vcard_apdu_delete(apdu);
+    vcard_free(card); /* free our reference */
+    return VREADER_OK;
+}
+
+struct VReaderListStruct {
+    VReaderListEntry *head;
+    VReaderListEntry *tail;
+};
+
+struct VReaderListEntryStruct {
+    VReaderListEntry *next;
+    VReaderListEntry *prev;
+    VReader *reader;
+};
+
+
+static VReaderListEntry *
+vreader_list_entry_new(VReader *reader)
+{
+    VReaderListEntry *new_reader_list_entry;
+
+    new_reader_list_entry = (VReaderListEntry *)
+                               qemu_malloc(sizeof(VReaderListEntry));
+    new_reader_list_entry->next = NULL;
+    new_reader_list_entry->prev = NULL;
+    new_reader_list_entry->reader = vreader_reference(reader);
+    return new_reader_list_entry;
+}
+
+static void
+vreader_list_entry_delete(VReaderListEntry *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+    vreader_free(entry->reader);
+    qemu_free(entry);
+}
+
+
+static VReaderList *
+vreader_list_new(void)
+{
+    VReaderList *new_reader_list;
+
+    new_reader_list = (VReaderList *)qemu_malloc(sizeof(VReaderList));
+    new_reader_list->head = NULL;
+    new_reader_list->tail = NULL;
+    return new_reader_list;
+}
+
+void
+vreader_list_delete(VReaderList *list)
+{
+    VReaderListEntry *current_entry;
+    VReaderListEntry *next_entry = NULL;
+    for (current_entry = vreader_list_get_first(list); current_entry;
+         current_entry = next_entry) {
+        next_entry = vreader_list_get_next(current_entry);
+        vreader_list_entry_delete(current_entry);
+    }
+    list->head = NULL;
+    list->tail = NULL;
+    qemu_free(list);
+}
+
+
+VReaderListEntry *
+vreader_list_get_first(VReaderList *list)
+{
+    return list ? list->head : NULL;
+}
+
+VReaderListEntry *
+vreader_list_get_next(VReaderListEntry *current)
+{
+    return current ? current->next : NULL;
+}
+
+VReader *
+vreader_list_get_reader(VReaderListEntry *entry)
+{
+    return entry ? vreader_reference(entry->reader) : NULL;
+}
+
+static void
+vreader_queue(VReaderList *list, VReaderListEntry *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+    entry->next = NULL;
+    entry->prev = list->tail;
+    if (list->head) {
+        list->tail->next = entry;
+    } else {
+        list->head = entry;
+    }
+    list->tail = entry;
+}
+
+static void
+vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+    if (entry->next == NULL) {
+        list->tail = entry->prev;
+    } else if (entry->prev == NULL) {
+        list->head = entry->next;
+    } else {
+        entry->prev->next = entry->next;
+        entry->next->prev = entry->prev;
+    }
+    if ((list->tail == NULL) || (list->head == NULL)) {
+        list->head = list->tail = NULL;
+    }
+    entry->next = entry->prev = NULL;
+}
+
+static VReaderList *vreader_list;
+static QemuMutex vreader_list_mutex;
+
+static void
+vreader_list_init(void)
+{
+    vreader_list = vreader_list_new();
+    qemu_mutex_init(&vreader_list_mutex);
+}
+
+static void
+vreader_list_lock(void)
+{
+    qemu_mutex_lock(&vreader_list_mutex);
+}
+
+static void
+vreader_list_unlock(void)
+{
+    qemu_mutex_unlock(&vreader_list_mutex);
+}
+
+static VReaderList *
+vreader_copy_list(VReaderList *list)
+{
+    VReaderList *new_list = NULL;
+    VReaderListEntry *current_entry = NULL;
+
+    new_list = vreader_list_new();
+    if (new_list == NULL) {
+        return NULL;
+    }
+    for (current_entry = vreader_list_get_first(list); current_entry;
+         current_entry = vreader_list_get_next(current_entry)) {
+        VReader *reader = vreader_list_get_reader(current_entry);
+        VReaderListEntry *new_entry = vreader_list_entry_new(reader);
+
+        vreader_free(reader);
+        vreader_queue(new_list, new_entry);
+    }
+    return new_list;
+}
+
+VReaderList *
+vreader_get_reader_list(void)
+{
+    VReaderList *new_reader_list;
+
+    vreader_list_lock();
+    new_reader_list = vreader_copy_list(vreader_list);
+    vreader_list_unlock();
+    return new_reader_list;
+}
+
+VReader *
+vreader_get_reader_by_id(vreader_id_t id)
+{
+    VReader *reader = NULL;
+    VReaderListEntry *current_entry = NULL;
+
+    if (id == (vreader_id_t) -1) {
+        return NULL;
+    }
+
+    vreader_list_lock();
+    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
+            current_entry = vreader_list_get_next(current_entry)) {
+        VReader *creader = vreader_list_get_reader(current_entry);
+        if (creader->id == id) {
+            reader = creader;
+            break;
+        }
+        vreader_free(creader);
+    }
+    vreader_list_unlock();
+    return reader;
+}
+
+VReader *
+vreader_get_reader_by_name(const char *name)
+{
+    VReader *reader = NULL;
+    VReaderListEntry *current_entry = NULL;
+
+    vreader_list_lock();
+    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
+            current_entry = vreader_list_get_next(current_entry)) {
+        VReader *creader = vreader_list_get_reader(current_entry);
+        if (strcmp(creader->name, name) == 0) {
+            reader = creader;
+            break;
+        }
+        vreader_free(creader);
+    }
+    vreader_list_unlock();
+    return reader;
+}
+
+/* called from card_emul to initialize the readers */
+VReaderStatus
+vreader_add_reader(VReader *reader)
+{
+    VReaderListEntry *reader_entry;
+
+    reader_entry = vreader_list_entry_new(reader);
+    if (reader_entry == NULL) {
+        return VREADER_OUT_OF_MEMORY;
+    }
+    vreader_list_lock();
+    vreader_queue(vreader_list, reader_entry);
+    vreader_list_unlock();
+    vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
+    return VREADER_OK;
+}
+
+
+VReaderStatus
+vreader_remove_reader(VReader *reader)
+{
+    VReaderListEntry *current_entry;
+
+    vreader_list_lock();
+    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
+         current_entry = vreader_list_get_next(current_entry)) {
+        if (current_entry->reader == reader) {
+            break;
+        }
+    }
+    vreader_dequeue(vreader_list, current_entry);
+    vreader_list_unlock();
+    vreader_list_entry_delete(current_entry);
+    vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
+    return VREADER_OK;
+}
+
+/*
+ * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
+ * state. Separated from vreader_insert_card to allow replaying events
+ * for a given state.
+ */
+void
+vreader_queue_card_event(VReader *reader)
+{
+    vevent_queue_vevent(vevent_new(
+        reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
+        reader->card));
+}
+
+/*
+ * insert/remove a new card. for removal, card == NULL
+ */
+VReaderStatus
+vreader_insert_card(VReader *reader, VCard *card)
+{
+    vreader_lock(reader);
+    if (reader->card) {
+        /* decrement reference count */
+        vcard_free(reader->card);
+        reader->card = NULL;
+    }
+    reader->card = vcard_reference(card);
+    vreader_unlock(reader);
+    vreader_queue_card_event(reader);
+    return VREADER_OK;
+}
+
+/*
+ * initialize all the static reader structures
+ */
+void
+vreader_init(void)
+{
+    vreader_list_init();
+}
+
diff --git a/libcacard/vreader.h b/libcacard/vreader.h
new file mode 100644
index 0000000..ec20421
--- /dev/null
+++ b/libcacard/vreader.h
@@ -0,0 +1,55 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef VREADER_H
+#define VREADER_H 1
+
+#include "eventt.h"
+#include "vreadert.h"
+#include "vcardt.h"
+
+/*
+ * calls for reader front end
+ */
+VReaderStatus vreader_power_on(VReader *reader, unsigned char *atr, int *len);
+VReaderStatus vreader_power_off(VReader *reader);
+VReaderStatus vreader_xfr_bytes(VReader *reader, unsigned char *send_buf,
+                                int send_buf_len, unsigned char *receive_buf,
+                                int *receive_buf_len);
+
+/* constructor */
+VReader *vreader_new(const char *readerName, VReaderEmul *emul_private,
+                     VReaderEmulFree private_free);
+/* get a new reference to a reader */
+VReader *vreader_reference(VReader *reader);
+/* "destructor" (readers are reference counted) */
+void vreader_free(VReader *reader);
+
+/* accessors */
+VReaderEmul *vreader_get_private(VReader *);
+VReaderStatus vreader_card_is_present(VReader *reader);
+void vreader_queue_card_event(VReader *reader);
+const char *vreader_get_name(VReader *reader);
+vreader_id_t vreader_get_id(VReader *reader);
+VReaderStatus vreader_set_id(VReader *reader, vreader_id_t id);
+
+/* list operations */
+VReaderList *vreader_get_reader_list(void);
+void vreader_list_delete(VReaderList *list);
+VReader *vreader_list_get_reader(VReaderListEntry *entry);
+VReaderListEntry *vreader_list_get_first(VReaderList *list);
+VReaderListEntry *vreader_list_get_next(VReaderListEntry *list);
+VReader *vreader_get_reader_by_id(vreader_id_t id);
+VReader *vreader_get_reader_by_name(const char *name);
+
+/*
+ * list tools for vcard_emul
+ */
+void vreader_init(void);
+VReaderStatus vreader_add_reader(VReader *reader);
+VReaderStatus vreader_remove_reader(VReader *reader);
+VReaderStatus vreader_insert_card(VReader *reader, VCard *card);
+
+#endif
diff --git a/libcacard/vreadert.h b/libcacard/vreadert.h
new file mode 100644
index 0000000..f97e0a7
--- /dev/null
+++ b/libcacard/vreadert.h
@@ -0,0 +1,24 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef VREADERT_H
+#define VREADERT_H 1
+
+typedef enum {
+    VREADER_OK = 0,
+    VREADER_NO_CARD,
+    VREADER_OUT_OF_MEMORY
+} VReaderStatus;
+
+typedef unsigned int vreader_id_t;
+typedef struct VReaderStruct VReader;
+typedef struct VReaderListStruct VReaderList;
+typedef struct VReaderListEntryStruct VReaderListEntry;
+
+typedef struct VReaderEmulStruct VReaderEmul;
+typedef void (*VReaderEmulFree)(VReaderEmul *);
+
+#endif
+
commit edbb21363fbfe40e050f583df921484cbc31c79d
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Oct 17 13:10:32 2010 +0200

    ccid: add passthru card device
    
    The passthru ccid card is a device sitting on the usb-ccid bus and
    using a chardevice to communicate with a remote device using the
    VSCard protocol defined in libcacard/vscard_common.h
    
    Usage docs available in following patch in docs/ccid.txt
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    ---
    
    Changes from v23->v24:
     * fixed double license line in header.
    
    Changes from v20->v21: (Jes Sorensen review)
     * add reference to COPYING in header
     * long comment reformatting
    
    Changes from v19->v20:
     * checkpatch.pl
    
    Changes from v18->v19:
     * add qdev.desc
     * remove .qdev.unplug (no hot unplug support for ccid bus)
    
    Changes from v16->v17:
     * fix wrong cast when receiving VSC_Error
     * ccid-card-passthru: force chardev user wakeup by sending Init
       see lengthy comment below.
    
    Changes from v15->v16:
    
    Behavioral changes:
     * return correct size
     * return error instead of assert if client sent too large ATR
     * don't assert if client sent too large a size, but add asserts for indices to buffer
     * reset vscard_in indices on chardev disconnect
     * handle init from client
     * error if no chardev supplied
     * use ntoh, hton
     * eradicate reader_id_t
     * remove Reconnect usage (removed from VSCARD protocol)
     * send VSC_SUCCESS on card insert/remove and reader add/remove
    
    Style fixes:
     * width of line fix
     * update copyright
     * remove old TODO's
     * update file header comment
     * use macros for debug levels
     * c++ style comment replacement
     * update copyright license
     * fix ATR size comment
     * fix whitespace in struct def
     * fix DPRINTF prefix
     * line width fix
    
    ccid-card-passthru: force chardev user wakeup by sending Init
    
    The problem: how to wakeup the user of the smartcard when the smartcard
    device is initialized?
    
    Long term solution: have a callback interface. This was done via
    the deprecated so called chardev ioctl interface.
    
    Short term solution: do a write. Specifically we write an Init message.
    And we change the client to send it's own Init message regardless of
    receiving this one. Additional Init messages will be regarded as
    acceptable, the first one received after connection establishment is
    the determining one wrt capabilities.

diff --git a/Makefile.objs b/Makefile.objs
index 7fdfc48..07063f1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -200,7 +200,7 @@ hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 hw-obj-$(CONFIG_DMA) += dma.o
 hw-obj-$(CONFIG_HPET) += hpet.o
 hw-obj-$(CONFIG_APPLESMC) += applesmc.o
-hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o
+hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
new file mode 100644
index 0000000..8506fed
--- /dev/null
+++ b/hw/ccid-card-passthru.c
@@ -0,0 +1,340 @@
+/*
+ * CCID Passthru Card Device emulation
+ *
+ * Copyright (c) 2011 Red Hat.
+ * Written by Alon Levy.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <arpa/inet.h>
+
+#include "qemu-char.h"
+#include "monitor.h"
+#include "hw/ccid.h"
+#include "libcacard/vscard_common.h"
+
+#define DPRINTF(card, lvl, fmt, ...)                    \
+do {                                                    \
+    if (lvl <= card->debug) {                           \
+        printf("ccid-card-passthru: " fmt , ## __VA_ARGS__);     \
+    }                                                   \
+} while (0)
+
+#define D_WARN 1
+#define D_INFO 2
+#define D_MORE_INFO 3
+#define D_VERBOSE 4
+
+/* TODO: do we still need this? */
+uint8_t DEFAULT_ATR[] = {
+/*
+ * From some example somewhere
+ * 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28
+ */
+
+/* From an Athena smart card */
+ 0x3B, 0xD5, 0x18, 0xFF, 0x80, 0x91, 0xFE, 0x1F, 0xC3, 0x80, 0x73, 0xC8, 0x21,
+ 0x13, 0x08
+};
+
+
+#define PASSTHRU_DEV_NAME "ccid-card-passthru"
+#define VSCARD_IN_SIZE 65536
+
+/* maximum size of ATR - from 7816-3 */
+#define MAX_ATR_SIZE        40
+
+typedef struct PassthruState PassthruState;
+
+struct PassthruState {
+    CCIDCardState base;
+    CharDriverState *cs;
+    uint8_t  vscard_in_data[VSCARD_IN_SIZE];
+    uint32_t vscard_in_pos;
+    uint32_t vscard_in_hdr;
+    uint8_t  atr[MAX_ATR_SIZE];
+    uint8_t  atr_length;
+    uint8_t  debug;
+};
+
+/*
+ * VSCard protocol over chardev
+ * This code should not depend on the card type.
+ */
+
+static void ccid_card_vscard_send_msg(PassthruState *s,
+        VSCMsgType type, uint32_t reader_id,
+        const uint8_t *payload, uint32_t length)
+{
+    VSCMsgHeader scr_msg_header;
+
+    scr_msg_header.type = htonl(type);
+    scr_msg_header.reader_id = htonl(reader_id);
+    scr_msg_header.length = htonl(length);
+    qemu_chr_write(s->cs, (uint8_t *)&scr_msg_header, sizeof(VSCMsgHeader));
+    qemu_chr_write(s->cs, payload, length);
+}
+
+static void ccid_card_vscard_send_apdu(PassthruState *s,
+    const uint8_t *apdu, uint32_t length)
+{
+    ccid_card_vscard_send_msg(
+        s, VSC_APDU, VSCARD_MINIMAL_READER_ID, apdu, length);
+}
+
+static void ccid_card_vscard_send_error(PassthruState *s,
+                    uint32_t reader_id, VSCErrorCode code)
+{
+    VSCMsgError msg = {.code = htonl(code)};
+
+    ccid_card_vscard_send_msg(
+        s, VSC_Error, reader_id, (uint8_t *)&msg, sizeof(msg));
+}
+
+static void ccid_card_vscard_send_init(PassthruState *s)
+{
+    VSCMsgInit msg = {
+        .version = htonl(VSCARD_VERSION),
+        .magic = VSCARD_MAGIC,
+        .capabilities = {0}
+    };
+
+    ccid_card_vscard_send_msg(s, VSC_Init, VSCARD_UNDEFINED_READER_ID,
+                         (uint8_t *)&msg, sizeof(msg));
+}
+
+static int ccid_card_vscard_can_read(void *opaque)
+{
+    PassthruState *card = opaque;
+
+    return VSCARD_IN_SIZE >= card->vscard_in_pos ?
+           VSCARD_IN_SIZE - card->vscard_in_pos : 0;
+}
+
+static void ccid_card_vscard_handle_init(
+    PassthruState *card, VSCMsgHeader *hdr, VSCMsgInit *init)
+{
+    uint32_t *capabilities;
+    int num_capabilities;
+    int i;
+
+    capabilities = init->capabilities;
+    num_capabilities =
+        1 + ((hdr->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+    init->version = ntohl(init->version);
+    for (i = 0 ; i < num_capabilities; ++i) {
+        capabilities[i] = ntohl(capabilities[i]);
+    }
+    if (init->magic != VSCARD_MAGIC) {
+        error_report("wrong magic");
+        /* we can't disconnect the chardev */
+    }
+    if (init->version != VSCARD_VERSION) {
+        DPRINTF(card, D_WARN,
+            "got version %d, have %d", init->version, VSCARD_VERSION);
+    }
+    /* future handling of capabilities, none exist atm */
+    ccid_card_vscard_send_init(card);
+}
+
+static void ccid_card_vscard_handle_message(PassthruState *card,
+    VSCMsgHeader *scr_msg_header)
+{
+    uint8_t *data = (uint8_t *)&scr_msg_header[1];
+
+    switch (scr_msg_header->type) {
+    case VSC_ATR:
+        DPRINTF(card, D_INFO, "VSC_ATR %d\n", scr_msg_header->length);
+        if (scr_msg_header->length > MAX_ATR_SIZE) {
+            error_report("ATR size exceeds spec, ignoring");
+            ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
+                                        VSC_GENERAL_ERROR);
+        }
+        memcpy(card->atr, data, scr_msg_header->length);
+        card->atr_length = scr_msg_header->length;
+        ccid_card_card_inserted(&card->base);
+        ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
+                                    VSC_SUCCESS);
+        break;
+    case VSC_APDU:
+        ccid_card_send_apdu_to_guest(
+            &card->base, data, scr_msg_header->length);
+        break;
+    case VSC_CardRemove:
+        DPRINTF(card, D_INFO, "VSC_CardRemove\n");
+        ccid_card_card_removed(&card->base);
+        ccid_card_vscard_send_error(card,
+            scr_msg_header->reader_id, VSC_SUCCESS);
+        break;
+    case VSC_Init:
+        ccid_card_vscard_handle_init(
+            card, scr_msg_header, (VSCMsgInit *)data);
+        break;
+    case VSC_Error:
+        ccid_card_card_error(&card->base, *(uint32_t *)data);
+        break;
+    case VSC_ReaderAdd:
+        if (ccid_card_ccid_attach(&card->base) < 0) {
+            ccid_card_vscard_send_error(card, VSCARD_UNDEFINED_READER_ID,
+                                      VSC_CANNOT_ADD_MORE_READERS);
+        } else {
+            ccid_card_vscard_send_error(card, VSCARD_MINIMAL_READER_ID,
+                                        VSC_SUCCESS);
+        }
+        break;
+    case VSC_ReaderRemove:
+        ccid_card_ccid_detach(&card->base);
+        ccid_card_vscard_send_error(card,
+            scr_msg_header->reader_id, VSC_SUCCESS);
+        break;
+    default:
+        printf("usb-ccid: chardev: unexpected message of type %X\n",
+               scr_msg_header->type);
+        ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
+            VSC_GENERAL_ERROR);
+    }
+}
+
+static void ccid_card_vscard_drop_connection(PassthruState *card)
+{
+    qemu_chr_close(card->cs);
+    card->vscard_in_pos = card->vscard_in_hdr = 0;
+}
+
+static void ccid_card_vscard_read(void *opaque, const uint8_t *buf, int size)
+{
+    PassthruState *card = opaque;
+    VSCMsgHeader *hdr;
+
+    if (card->vscard_in_pos + size > VSCARD_IN_SIZE) {
+        error_report(
+            "no room for data: pos %d +  size %d > %d. dropping connection.",
+            card->vscard_in_pos, size, VSCARD_IN_SIZE);
+        ccid_card_vscard_drop_connection(card);
+        return;
+    }
+    assert(card->vscard_in_pos < VSCARD_IN_SIZE);
+    assert(card->vscard_in_hdr < VSCARD_IN_SIZE);
+    memcpy(card->vscard_in_data + card->vscard_in_pos, buf, size);
+    card->vscard_in_pos += size;
+    hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
+
+    while ((card->vscard_in_pos - card->vscard_in_hdr >= sizeof(VSCMsgHeader))
+         &&(card->vscard_in_pos - card->vscard_in_hdr >=
+                                  sizeof(VSCMsgHeader) + ntohl(hdr->length))) {
+        hdr->reader_id = ntohl(hdr->reader_id);
+        hdr->length = ntohl(hdr->length);
+        hdr->type = ntohl(hdr->type);
+        ccid_card_vscard_handle_message(card, hdr);
+        card->vscard_in_hdr += hdr->length + sizeof(VSCMsgHeader);
+        hdr = (VSCMsgHeader *)(card->vscard_in_data + card->vscard_in_hdr);
+    }
+    if (card->vscard_in_hdr == card->vscard_in_pos) {
+        card->vscard_in_pos = card->vscard_in_hdr = 0;
+    }
+}
+
+static void ccid_card_vscard_event(void *opaque, int event)
+{
+    PassthruState *card = opaque;
+
+    switch (event) {
+    case CHR_EVENT_BREAK:
+        card->vscard_in_pos = card->vscard_in_hdr = 0;
+        break;
+    case CHR_EVENT_FOCUS:
+        break;
+    case CHR_EVENT_OPENED:
+        DPRINTF(card, D_INFO, "%s: CHR_EVENT_OPENED\n", __func__);
+        break;
+    }
+}
+
+/* End VSCard handling */
+
+static void passthru_apdu_from_guest(
+    CCIDCardState *base, const uint8_t *apdu, uint32_t len)
+{
+    PassthruState *card = DO_UPCAST(PassthruState, base, base);
+
+    if (!card->cs) {
+        printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
+        return;
+    }
+    ccid_card_vscard_send_apdu(card, apdu, len);
+}
+
+static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
+{
+    PassthruState *card = DO_UPCAST(PassthruState, base, base);
+
+    *len = card->atr_length;
+    return card->atr;
+}
+
+static int passthru_initfn(CCIDCardState *base)
+{
+    PassthruState *card = DO_UPCAST(PassthruState, base, base);
+
+    card->vscard_in_pos = 0;
+    card->vscard_in_hdr = 0;
+    if (card->cs) {
+        DPRINTF(card, D_INFO, "initing chardev\n");
+        qemu_chr_add_handlers(card->cs,
+            ccid_card_vscard_can_read,
+            ccid_card_vscard_read,
+            ccid_card_vscard_event, card);
+        ccid_card_vscard_send_init(card);
+    } else {
+        error_report("missing chardev");
+        return -1;
+    }
+    assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
+    memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
+    card->atr_length = sizeof(DEFAULT_ATR);
+    return 0;
+}
+
+static int passthru_exitfn(CCIDCardState *base)
+{
+    return 0;
+}
+
+static VMStateDescription passthru_vmstate = {
+    .name = PASSTHRU_DEV_NAME,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_BUFFER(vscard_in_data, PassthruState),
+        VMSTATE_UINT32(vscard_in_pos, PassthruState),
+        VMSTATE_UINT32(vscard_in_hdr, PassthruState),
+        VMSTATE_BUFFER(atr, PassthruState),
+        VMSTATE_UINT8(atr_length, PassthruState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static CCIDCardInfo passthru_card_info = {
+    .qdev.name = PASSTHRU_DEV_NAME,
+    .qdev.desc = "passthrough smartcard",
+    .qdev.size = sizeof(PassthruState),
+    .qdev.vmsd = &passthru_vmstate,
+    .initfn = passthru_initfn,
+    .exitfn = passthru_exitfn,
+    .get_atr = passthru_get_atr,
+    .apdu_from_guest = passthru_apdu_from_guest,
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_CHR("chardev", PassthruState, cs),
+        DEFINE_PROP_UINT8("debug", PassthruState, debug, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void ccid_card_passthru_register_devices(void)
+{
+    ccid_card_qdev_register(&passthru_card_info);
+}
+
+device_init(ccid_card_passthru_register_devices)
commit 0c16524709f38bb529f68c0921e72207606c57b1
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Feb 2 21:48:04 2011 +0200

    introduce libcacard/vscard_common.h
    
    ---
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    v20->v21 changes: (Jes Sorensen review)
     * license set to 2+
     * long comment fixes, remove empty line at eof.
     * add reference to COPYING
    
    v19->v20 changes:
     * checkpatch.pl
    
    v15->v16 changes:
    
    Protocol change:
     * VSCMsgInit capabilities and magic
     * removed ReaderResponse, will use Error instead with code==VSC_SUCCESS.
     * adaded Flush and FlushComplete, remove Reconnect.
     * define VSCARD_MAGIC
     * added error code VSC_SUCCESS.
    
    Fixes:
     * update VSCMsgInit comment
     * fix message type enum
     * remove underscore from wrapping define
     * update copyright
     * updated comments.
     * Header comment updated
     * remove C++ style comment
     * fix comment for VSCMsgError
     * give names to enums in typedefs

diff --git a/libcacard/vscard_common.h b/libcacard/vscard_common.h
new file mode 100644
index 0000000..bebd52d
--- /dev/null
+++ b/libcacard/vscard_common.h
@@ -0,0 +1,178 @@
+/* Virtual Smart Card protocol definition
+ *
+ * This protocol is between a host using virtual smart card readers,
+ * and a client providing the smart cards, perhaps by emulating them or by
+ * access to real cards.
+ *
+ * Definitions for this protocol:
+ *  Host   - user of the card
+ *  Client - owner of the card
+ *
+ * The current implementation passes the raw APDU's from 7816 and additionally
+ * contains messages to setup and teardown readers, handle insertion and
+ * removal of cards, negotiate the protocol via capabilities and provide
+ * for error responses.
+ *
+ * Copyright (c) 2011 Red Hat.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef VSCARD_COMMON_H
+#define VSCARD_COMMON_H
+
+#include <stdint.h>
+
+#define VERSION_MAJOR_BITS 11
+#define VERSION_MIDDLE_BITS 11
+#define VERSION_MINOR_BITS 10
+
+#define MAKE_VERSION(major, middle, minor) \
+     ((major  << (VERSION_MINOR_BITS + VERSION_MIDDLE_BITS)) \
+      | (middle <<  VERSION_MINOR_BITS) \
+      | (minor))
+
+/*
+ * IMPORTANT NOTE on VERSION
+ *
+ * The version below MUST be changed whenever a change in this file is made.
+ *
+ * The last digit, the minor, is for bug fix changes only.
+ *
+ * The middle digit is for backward / forward compatible changes, updates
+ * to the existing messages, addition of fields.
+ *
+ * The major digit is for a breaking change of protocol, presumably
+ * something that cannot be accomodated with the existing protocol.
+ */
+
+#define VSCARD_VERSION MAKE_VERSION(0, 0, 2)
+
+typedef enum VSCMsgType {
+    VSC_Init = 1,
+    VSC_Error,
+    VSC_ReaderAdd,
+    VSC_ReaderRemove,
+    VSC_ATR,
+    VSC_CardRemove,
+    VSC_APDU,
+    VSC_Flush,
+    VSC_FlushComplete
+} VSCMsgType;
+
+typedef enum VSCErrorCode {
+    VSC_SUCCESS = 0,
+    VSC_GENERAL_ERROR = 1,
+    VSC_CANNOT_ADD_MORE_READERS,
+    VSC_CARD_ALREAY_INSERTED,
+} VSCErrorCode;
+
+#define VSCARD_UNDEFINED_READER_ID  0xffffffff
+#define VSCARD_MINIMAL_READER_ID    0
+
+#define VSCARD_MAGIC (*(uint32_t *)"VSCD")
+
+/*
+ * Header
+ * Each message starts with the header.
+ * type - message type
+ * reader_id - used by messages that are reader specific
+ * length - length of payload (not including header, i.e. zero for
+ *  messages containing empty payloads)
+ */
+typedef struct VSCMsgHeader {
+    uint32_t   type;
+    uint32_t   reader_id;
+    uint32_t   length;
+    uint8_t    data[0];
+} VSCMsgHeader;
+
+/*
+ * VSCMsgInit               Client <-> Host
+ * Client sends it on connection, with its own capabilities.
+ * Host replies with VSCMsgInit filling in its capabilities.
+ *
+ * It is not meant to be used for negotiation, i.e. sending more then
+ * once from any side, but could be used for that in the future.
+ */
+typedef struct VSCMsgInit {
+    uint32_t   magic;
+    uint32_t   version;
+    uint32_t   capabilities[1]; /* receiver must check length,
+                                   array may grow in the future*/
+} VSCMsgInit;
+
+/*
+ * VSCMsgError              Client <-> Host
+ * This message is a response to any of:
+ *  Reader Add
+ *  Reader Remove
+ *  Card Remove
+ * If the operation was successful then VSC_SUCCESS
+ * is returned, other wise a specific error code.
+ */
+typedef struct VSCMsgError {
+    uint32_t   code;
+} VSCMsgError;
+
+/*
+ * VSCMsgReaderAdd          Client -> Host
+ * Host replies with allocated reader id in VSCMsgError with code==SUCCESS.
+ *
+ * name - name of the reader on client side, UTF-8 encoded. Only used
+ *  for client presentation (may be translated to the device presented to the
+ *  guest), protocol wise only reader_id is important.
+ */
+typedef struct VSCMsgReaderAdd {
+    uint8_t    name[0];
+} VSCMsgReaderAdd;
+
+/*
+ * VSCMsgReaderRemove       Client -> Host
+ * The client's reader has been removed.
+ */
+typedef struct VSCMsgReaderRemove {
+} VSCMsgReaderRemove;
+
+/*
+ * VSCMsgATR                Client -> Host
+ * Answer to reset. Sent for card insertion or card reset. The reset/insertion
+ * happens on the client side, they do not require any action from the host.
+ */
+typedef struct VSCMsgATR {
+    uint8_t     atr[0];
+} VSCMsgATR;
+
+/*
+ * VSCMsgCardRemove         Client -> Host
+ * The client card has been removed.
+ */
+typedef struct VSCMsgCardRemove {
+} VSCMsgCardRemove;
+
+/*
+ * VSCMsgAPDU               Client <-> Host
+ * Main reason of existance. Transfer a single APDU in either direction.
+ */
+typedef struct VSCMsgAPDU {
+    uint8_t    data[0];
+} VSCMsgAPDU;
+
+/*
+ * VSCMsgFlush               Host -> Client
+ * Request client to send a FlushComplete message when it is done
+ * servicing all outstanding APDUs
+ */
+typedef struct VSCMsgFlush {
+} VSCMsgFlush;
+
+/*
+ * VSCMsgFlush               Client -> Host
+ * Client response to Flush after all APDUs have been processed and
+ * responses sent.
+ */
+typedef struct VSCMsgFlushComplete {
+} VSCMsgFlushComplete;
+
+#endif /* VSCARD_COMMON_H */
commit 367071447ec5b0dabc5452384bbeb62371838112
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Oct 17 11:40:07 2010 +0200

    usb-ccid: add CCID bus
    
    A CCID device is a smart card reader. It is a USB device, defined at [1].
    This patch introduces the usb-ccid device that is a ccid bus. Next patches will
    introduce two card types to use it, a passthru card and an emulated card.
    
     [1] http://www.usb.org/developers/devclass_docs/DWG_Smart-Card_CCID_Rev110.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    
    ---
    
    changes from v20->v21: (Jes Sorenson review)
     * cosmetic changes - fix multi line comments.
     * reorder fields in USBCCIDState
     * add reference to COPYING
     * add --enable-smartcard and --disable-smartcard here (moved
     from last patch)
    
    changes from v19->v20:
     * checkpatch.pl
    
    changes from v18->v19:
     * merged: ccid.h: add copyright, fix define and remove non C89 comments
     * add qdev.desc
    
    changes from v15->v16:
    
    Behavioral changes:
     * fix abort on client answer after card remove
     * enable migration
     * remove side affect code from asserts
     * return consistent self-powered state
     * mask out reserved bits in ccid_set_parameters
     * add missing abRFU in SetParameters (no affect on linux guest)
    
    whitefixes / comments / consts defines:
     * remove stale comment
     * remove ccid_print_pending_answers if no DEBUG_CCID
     * replace printf's with DPRINTF, remove DEBUG_CCID, add verbosity defines
     * use error_report
     * update copyright (most of the code is not original)
     * reword known bug comment
     * add missing closing quote in comment
     * add missing whitespace on one line
     * s/CCID_SetParameter/CCID_SetParameters/
     * add comments
     * use define for max packet size
    
    Comment for "return consistent self-powered state":
    
    the Configuration Descriptor bmAttributes claims we are self powered,
    but we were returning not self powered to USB_REQ_GET_STATUS control message.
    
    In practice, this message is not sent by a linux 2.6.35.10-74.fc14.x86_64
    guest (not tested on other guests), unless you issue lsusb -v as root (for
    example).

diff --git a/Makefile.objs b/Makefile.objs
index d906a8e..7fdfc48 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -200,6 +200,7 @@ hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 hw-obj-$(CONFIG_DMA) += dma.o
 hw-obj-$(CONFIG_HPET) += hpet.o
 hw-obj-$(CONFIG_APPLESMC) += applesmc.o
+hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/configure b/configure
index 7d8d890..01ee94d 100755
--- a/configure
+++ b/configure
@@ -175,6 +175,7 @@ trace_backend="nop"
 trace_file="trace"
 spice=""
 rbd=""
+smartcard=""
 
 # parse CC options first
 for opt do
@@ -724,6 +725,10 @@ for opt do
   ;;
   --enable-rbd) rbd="yes"
   ;;
+  --disable-smartcard) smartcard="no"
+  ;;
+  --enable-smartcard) smartcard="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -921,6 +926,8 @@ echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
 echo "  --enable-rbd             enable building the rados block device (rbd)"
+echo "  --disable-smartcard      disable smartcard support"
+echo "  --enable-smartcard       enable smartcard support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2824,6 +2831,10 @@ if test "$spice" = "yes" ; then
   echo "CONFIG_SPICE=y" >> $config_host_mak
 fi
 
+if test "$smartcard" = "yes" ; then
+  echo "CONFIG_SMARTCARD=y" >> $config_host_mak
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "CONFIG_BSD=y" >> $config_host_mak
diff --git a/hw/ccid.h b/hw/ccid.h
new file mode 100644
index 0000000..dbfc13c
--- /dev/null
+++ b/hw/ccid.h
@@ -0,0 +1,59 @@
+/*
+ * CCID Passthru Card Device emulation
+ *
+ * Copyright (c) 2011 Red Hat.
+ * Written by Alon Levy.
+ *
+ * This code is licenced under the GNU LGPL, version 2 or later.
+ */
+
+#ifndef CCID_H
+#define CCID_H
+
+#include "qdev.h"
+
+typedef struct CCIDCardState CCIDCardState;
+typedef struct CCIDCardInfo CCIDCardInfo;
+
+/*
+ * state of the CCID Card device (i.e. hw/ccid-card-*.c)
+ */
+struct CCIDCardState {
+    DeviceState qdev;
+    uint32_t    slot; /* For future use with multiple slot reader. */
+};
+
+/*
+ * callbacks to be used by the CCID device (hw/usb-ccid.c) to call
+ * into the smartcard device (hw/ccid-card-*.c)
+ */
+struct CCIDCardInfo {
+    DeviceInfo qdev;
+    void (*print)(Monitor *mon, CCIDCardState *card, int indent);
+    const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
+    void (*apdu_from_guest)(CCIDCardState *card,
+                            const uint8_t *apdu,
+                            uint32_t len);
+    int (*exitfn)(CCIDCardState *card);
+    int (*initfn)(CCIDCardState *card);
+};
+
+/*
+ * API for smartcard calling the CCID device (used by hw/ccid-card-*.c)
+ */
+void ccid_card_send_apdu_to_guest(CCIDCardState *card,
+                                  uint8_t *apdu,
+                                  uint32_t len);
+void ccid_card_card_removed(CCIDCardState *card);
+void ccid_card_card_inserted(CCIDCardState *card);
+void ccid_card_card_error(CCIDCardState *card, uint64_t error);
+void ccid_card_qdev_register(CCIDCardInfo *card);
+
+/*
+ * support guest visible insertion/removal of ccid devices based on actual
+ * devices connected/removed. Called by card implementation (passthru, local)
+ */
+int ccid_card_ccid_attach(CCIDCardState *card);
+void ccid_card_ccid_detach(CCIDCardState *card);
+
+#endif /* CCID_H */
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
new file mode 100644
index 0000000..723b2e3
--- /dev/null
+++ b/hw/usb-ccid.c
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * CCID Device emulation
+ *
+ * Written by Alon Levy, with contributions from Robert Relyea.
+ *
+ * Based on usb-serial.c, see it's copyright and attributions below.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ * ------- (original copyright & attribution for usb-serial.c below) --------
+ * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2008 Samuel Thibault <samuel.thibault at ens-lyon.org>
+ * Written by Paul Brook, reused for FTDI by Samuel Thibault,
+ */
+
+/*
+ * References:
+ *
+ * CCID Specification Revision 1.1 April 22nd 2005
+ *  "Universal Serial Bus, Device Class: Smart Card"
+ *  Specification for Integrated Circuit(s) Cards Interface Devices
+ *
+ * Endianess note: from the spec (1.3)
+ *  "Fields that are larger than a byte are stored in little endian"
+ *
+ * KNOWN BUGS
+ * 1. remove/insert can sometimes result in removed state instead of inserted.
+ * This is a result of the following:
+ *  symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This can happen
+ *  when a short packet is sent, as seen in uhci-usb.c, resulting from a urb
+ *  from the guest requesting SPD and us returning a smaller packet.
+ *  Not sure which messages trigger this.
+ */
+
+#include "qemu-common.h"
+#include "qemu-error.h"
+#include "usb.h"
+#include "monitor.h"
+
+#include "hw/ccid.h"
+
+#define DPRINTF(s, lvl, fmt, ...) \
+do { \
+    if (lvl <= s->debug) { \
+        printf("usb-ccid: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+#define D_WARN 1
+#define D_INFO 2
+#define D_MORE_INFO 3
+#define D_VERBOSE 4
+
+#define CCID_DEV_NAME "usb-ccid"
+
+/*
+ * The two options for variable sized buffers:
+ * make them constant size, for large enough constant,
+ * or handle the migration complexity - VMState doesn't handle this case.
+ * sizes are expected never to be exceeded, unless guest misbehaves.
+ */
+#define BULK_OUT_DATA_SIZE 65536
+#define PENDING_ANSWERS_NUM 128
+
+#define BULK_IN_BUF_SIZE 384
+#define BULK_IN_PENDING_NUM 8
+
+#define InterfaceOutClass \
+    ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+
+#define InterfaceInClass  \
+    ((USB_DIR_IN  | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+
+#define CCID_MAX_PACKET_SIZE                64
+
+#define CCID_CONTROL_ABORT                  0x1
+#define CCID_CONTROL_GET_CLOCK_FREQUENCIES  0x2
+#define CCID_CONTROL_GET_DATA_RATES         0x3
+
+#define CCID_PRODUCT_DESCRIPTION        "QEMU USB CCID"
+#define CCID_VENDOR_DESCRIPTION         "QEMU " QEMU_VERSION
+#define CCID_INTERFACE_NAME             "CCID Interface"
+#define CCID_SERIAL_NUMBER_STRING       "1"
+/*
+ * Using Gemplus Vendor and Product id
+ * Effect on various drivers:
+ *  usbccid.sys (winxp, others untested) is a class driver so it doesn't care.
+ *  linux has a number of class drivers, but openct filters based on
+ *   vendor/product (/etc/openct.conf under fedora), hence Gemplus.
+ */
+#define CCID_VENDOR_ID                  0x08e6
+#define CCID_PRODUCT_ID                 0x4433
+#define CCID_DEVICE_VERSION             0x0000
+
+/*
+ * BULK_OUT messages from PC to Reader
+ * Defined in CCID Rev 1.1 6.1 (page 26)
+ */
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn              0x62
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff             0x63
+#define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus           0x65
+#define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock                0x6f
+#define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters           0x6c
+#define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters         0x6d
+#define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters           0x61
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Escape                  0x6b
+#define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock                0x6e
+#define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU                  0x6a
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Secure                  0x69
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical              0x71
+#define CCID_MESSAGE_TYPE_PC_to_RDR_Abort                   0x72
+#define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73
+
+/*
+ * BULK_IN messages from Reader to PC
+ * Defined in CCID Rev 1.1 6.2 (page 48)
+ */
+#define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock               0x80
+#define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus              0x81
+#define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters              0x82
+#define CCID_MESSAGE_TYPE_RDR_to_PC_Escape                  0x83
+#define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84
+
+/*
+ * INTERRUPT_IN messages from Reader to PC
+ * Defined in CCID Rev 1.1 6.3 (page 56)
+ */
+#define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange        0x50
+#define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError           0x51
+
+/*
+ * Endpoints for CCID - addresses are up to us to decide.
+ * To support slot insertion and removal we must have an interrupt in ep
+ * in addition we need a bulk in and bulk out ep
+ * 5.2, page 20
+ */
+#define CCID_INT_IN_EP       1
+#define CCID_BULK_IN_EP      2
+#define CCID_BULK_OUT_EP     3
+
+/* bmSlotICCState masks */
+#define SLOT_0_STATE_MASK    1
+#define SLOT_0_CHANGED_MASK  2
+
+/* Status codes that go in bStatus (see 6.2.6) */
+enum {
+    ICC_STATUS_PRESENT_ACTIVE = 0,
+    ICC_STATUS_PRESENT_INACTIVE,
+    ICC_STATUS_NOT_PRESENT
+};
+
+enum {
+    COMMAND_STATUS_NO_ERROR = 0,
+    COMMAND_STATUS_FAILED,
+    COMMAND_STATUS_TIME_EXTENSION_REQUIRED
+};
+
+/* Error codes that go in bError (see 6.2.6) */
+enum {
+    ERROR_CMD_NOT_SUPPORTED = 0,
+    ERROR_CMD_ABORTED       = -1,
+    ERROR_ICC_MUTE          = -2,
+    ERROR_XFR_PARITY_ERROR  = -3,
+    ERROR_XFR_OVERRUN       = -4,
+    ERROR_HW_ERROR          = -5,
+};
+
+/* 6.2.6 RDR_to_PC_SlotStatus definitions */
+enum {
+    CLOCK_STATUS_RUNNING = 0,
+    /*
+     * 0 - Clock Running, 1 - Clock stopped in State L, 2 - H,
+     * 3 - unkonwn state. rest are RFU
+     */
+};
+
+typedef struct __attribute__ ((__packed__)) CCID_Header {
+    uint8_t     bMessageType;
+    uint32_t    dwLength;
+    uint8_t     bSlot;
+    uint8_t     bSeq;
+} CCID_Header;
+
+typedef struct __attribute__ ((__packed__)) CCID_BULK_IN {
+    CCID_Header hdr;
+    uint8_t     bStatus;        /* Only used in BULK_IN */
+    uint8_t     bError;         /* Only used in BULK_IN */
+} CCID_BULK_IN;
+
+typedef struct __attribute__ ((__packed__)) CCID_SlotStatus {
+    CCID_BULK_IN b;
+    uint8_t     bClockStatus;
+} CCID_SlotStatus;
+
+typedef struct __attribute__ ((__packed__)) CCID_Parameter {
+    CCID_BULK_IN b;
+    uint8_t     bProtocolNum;
+    uint8_t     abProtocolDataStructure[0];
+} CCID_Parameter;
+
+typedef struct __attribute__ ((__packed__)) CCID_DataBlock {
+    CCID_BULK_IN b;
+    uint8_t      bChainParameter;
+    uint8_t      abData[0];
+} CCID_DataBlock;
+
+/* 6.1.4 PC_to_RDR_XfrBlock */
+typedef struct __attribute__ ((__packed__)) CCID_XferBlock {
+    CCID_Header  hdr;
+    uint8_t      bBWI; /* Block Waiting Timeout */
+    uint16_t     wLevelParameter; /* XXX currently unused */
+    uint8_t      abData[0];
+} CCID_XferBlock;
+
+typedef struct __attribute__ ((__packed__)) CCID_IccPowerOn {
+    CCID_Header hdr;
+    uint8_t     bPowerSelect;
+    uint16_t    abRFU;
+} CCID_IccPowerOn;
+
+typedef struct __attribute__ ((__packed__)) CCID_IccPowerOff {
+    CCID_Header hdr;
+    uint16_t    abRFU;
+} CCID_IccPowerOff;
+
+typedef struct __attribute__ ((__packed__)) CCID_SetParameters {
+    CCID_Header hdr;
+    uint8_t     bProtocolNum;
+    uint16_t   abRFU;
+    uint8_t    abProtocolDataStructure[0];
+} CCID_SetParameters;
+
+typedef struct CCID_Notify_Slot_Change {
+    uint8_t     bMessageType; /* CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange */
+    uint8_t     bmSlotICCState;
+} CCID_Notify_Slot_Change;
+
+/* used for DataBlock response to XferBlock */
+typedef struct Answer {
+    uint8_t slot;
+    uint8_t seq;
+} Answer;
+
+/* pending BULK_IN messages */
+typedef struct BulkIn {
+    uint8_t  data[BULK_IN_BUF_SIZE];
+    uint32_t len;
+    uint32_t pos;
+} BulkIn;
+
+enum {
+    MIGRATION_NONE,
+    MIGRATION_MIGRATED,
+};
+
+typedef struct CCIDBus CCIDBus;
+typedef struct USBCCIDState USBCCIDState;
+
+#define MAX_PROTOCOL_SIZE   7
+
+/*
+ * powered - defaults to true, changed by PowerOn/PowerOff messages
+ */
+struct USBCCIDState {
+    USBDevice dev;
+    CCIDBus *bus;
+    CCIDCardState *card;
+    CCIDCardInfo *cardinfo; /* caching the info pointer */
+    BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
+    uint32_t bulk_in_pending_start;
+    uint32_t bulk_in_pending_end; /* first free */
+    uint32_t bulk_in_pending_num;
+    BulkIn *current_bulk_in;
+    uint8_t  bulk_out_data[BULK_OUT_DATA_SIZE];
+    uint32_t bulk_out_pos;
+    uint64_t last_answer_error;
+    Answer pending_answers[PENDING_ANSWERS_NUM];
+    uint32_t pending_answers_start;
+    uint32_t pending_answers_end;
+    uint32_t pending_answers_num;
+    uint8_t  bError;
+    uint8_t  bmCommandStatus;
+    uint8_t  bProtocolNum;
+    uint8_t  abProtocolDataStructure[MAX_PROTOCOL_SIZE];
+    uint32_t ulProtocolDataStructureSize;
+    uint32_t state_vmstate;
+    uint32_t migration_target_ip;
+    uint16_t migration_target_port;
+    uint8_t  migration_state;
+    uint8_t  bmSlotICCState;
+    uint8_t  powered;
+    uint8_t  notify_slot_change;
+    uint8_t  debug;
+};
+
+/*
+ * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
+ * "USB Device Framework", section 9.6.1, in the Universal Serial Bus
+ * Specification.
+ *
+ * This device implemented based on the spec and with an Athena Smart Card
+ * Reader as reference:
+ *   0dc3:1004 Athena Smartcard Solutions, Inc.
+ */
+
+static const uint8_t qemu_ccid_dev_descriptor[] = {
+        0x12,       /*  u8 bLength; */
+        USB_DT_DEVICE, /*  u8 bDescriptorType; Device */
+        0x10, 0x01, /*  u16 bcdUSB; v1.1 */
+
+        0x00,       /*  u8  bDeviceClass; */
+        0x00,       /*  u8  bDeviceSubClass; */
+        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
+        0x40,       /*  u8  bMaxPacketSize0; 8 Bytes (valid: 8,16,32,64) */
+
+        /* Vendor and product id are arbitrary.  */
+                    /*  u16 idVendor  */
+        CCID_VENDOR_ID & 0xff, CCID_VENDOR_ID >> 8,
+                    /*  u16 idProduct */
+        CCID_PRODUCT_ID & 0xff, CCID_PRODUCT_ID >> 8,
+                    /*  u16 bcdDevice */
+        CCID_DEVICE_VERSION & 0xff, CCID_DEVICE_VERSION >> 8,
+        0x01,       /*  u8  iManufacturer; */
+        0x02,       /*  u8  iProduct; */
+        0x03,       /*  u8  iSerialNumber; */
+        0x01,       /*  u8  bNumConfigurations; */
+};
+
+static const uint8_t qemu_ccid_config_descriptor[] = {
+
+        /* one configuration */
+        0x09,       /* u8  bLength; */
+        USB_DT_CONFIG, /* u8  bDescriptorType; Configuration */
+        0x5d, 0x00, /* u16 wTotalLength; 9+9+54+7+7+7 */
+        0x01,       /* u8  bNumInterfaces; (1) */
+        0x01,       /* u8  bConfigurationValue; */
+        0x00,       /* u8  iConfiguration; */
+        0xe0,       /* u8  bmAttributes;
+                                 Bit 7: must be set,
+                                     6: Self-powered,
+                                     5: Remote wakeup,
+                                     4..0: resvd */
+        100/2,      /* u8  MaxPower; 50 == 100mA */
+
+        /* one interface */
+        0x09,       /* u8  if_bLength; */
+        USB_DT_INTERFACE, /* u8  if_bDescriptorType; Interface */
+        0x00,       /* u8  if_bInterfaceNumber; */
+        0x00,       /* u8  if_bAlternateSetting; */
+        0x03,       /* u8  if_bNumEndpoints; */
+        0x0b,       /* u8  if_bInterfaceClass; Smart Card Device Class */
+        0x00,       /* u8  if_bInterfaceSubClass; Subclass code */
+        0x00,       /* u8  if_bInterfaceProtocol; Protocol code */
+        0x04,       /* u8  if_iInterface; Index of string descriptor */
+
+        /* Smart Card Device Class Descriptor */
+        0x36,       /* u8  bLength; */
+        0x21,       /* u8  bDescriptorType; Functional */
+        0x10, 0x01, /* u16 bcdCCID; CCID Specification Release Number. */
+        0x00,       /*
+                     * u8  bMaxSlotIndex; The index of the highest available
+                     * slot on this device. All slots are consecutive starting
+                     * at 00h.
+                     */
+        0x07,       /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
+
+        0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
+        0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
+                    /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
+        0xa0, 0x0f, 0x00, 0x00,
+                    /* u32 dwMaximumClock; */
+        0x00, 0x00, 0x01, 0x00,
+        0x00,       /* u8 bNumClockSupported;                 *
+                     *    0 means just the default and max.   */
+                    /* u32 dwDataRate ;bps. 9600 == 00002580h */
+        0x80, 0x25, 0x00, 0x00,
+                    /* u32 dwMaxDataRate ; 11520 bps == 0001C200h */
+        0x00, 0xC2, 0x01, 0x00,
+        0x00,       /* u8  bNumDataRatesSupported; 00 means all rates between
+                     *     default and max */
+                    /* u32 dwMaxIFSD;                                  *
+                     *     maximum IFSD supported by CCID for protocol *
+                     *     T=1 (Maximum seen from various cards)       */
+        0xfe, 0x00, 0x00, 0x00,
+                    /* u32 dwSyncProtocols; 1 - 2-wire, 2 - 3-wire, 4 - I2C */
+        0x00, 0x00, 0x00, 0x00,
+                    /* u32 dwMechanical;  0 - no special characteristics. */
+        0x00, 0x00, 0x00, 0x00,
+                    /*
+                     * u32 dwFeatures;
+                     * 0 - No special characteristics
+                     * + 2 Automatic parameter configuration based on ATR data
+                     * + 4 Automatic activation of ICC on inserting
+                     * + 8 Automatic ICC voltage selection
+                     * + 10 Automatic ICC clock frequency change
+                     * + 20 Automatic baud rate change
+                     * + 40 Automatic parameters negotiation made by the CCID
+                     * + 80 automatic PPS made by the CCID
+                     * 100 CCID can set ICC in clock stop mode
+                     * 200 NAD value other then 00 accepted (T=1 protocol)
+                     * + 400 Automatic IFSD exchange as first exchange (T=1)
+                     * One of the following only:
+                     * + 10000 TPDU level exchanges with CCID
+                     * 20000 Short APDU level exchange with CCID
+                     * 40000 Short and Extended APDU level exchange with CCID
+                     *
+                     * + 100000 USB Wake up signaling supported on card
+                     * insertion and removal. Must set bit 5 in bmAttributes
+                     * in Configuration descriptor if 100000 is set.
+                     */
+        0xfe, 0x04, 0x11, 0x00,
+                    /*
+                     * u32 dwMaxCCIDMessageLength; For extended APDU in
+                     * [261 + 10 , 65544 + 10]. Otherwise the minimum is
+                     * wMaxPacketSize of the Bulk-OUT endpoint
+                     */
+        0x12, 0x00, 0x01, 0x00,
+        0xFF,       /*
+                     * u8  bClassGetResponse; Significant only for CCID that
+                     * offers an APDU level for exchanges. Indicates the
+                     * default class value used by the CCID when it sends a
+                     * Get Response command to perform the transportation of
+                     * an APDU by T=0 protocol
+                     * FFh indicates that the CCID echos the class of the APDU.
+                     */
+        0xFF,       /*
+                     * u8  bClassEnvelope; EAPDU only. Envelope command for
+                     * T=0
+                     */
+        0x00, 0x00, /*
+                     * u16 wLcdLayout; XXYY Number of lines (XX) and chars per
+                     * line for LCD display used for PIN entry. 0000 - no LCD
+                     */
+        0x01,       /*
+                     * u8  bPINSupport; 01h PIN Verification,
+                     *                  02h PIN Modification
+                     */
+        0x01,       /* u8  bMaxCCIDBusySlots; */
+
+        /* Interrupt-IN endpoint */
+        0x07,       /* u8  ep_bLength; */
+                    /* u8  ep_bDescriptorType; Endpoint */
+        USB_DT_ENDPOINT,
+                    /* u8  ep_bEndpointAddress; IN Endpoint 1 */
+        0x80 | CCID_INT_IN_EP,
+        0x03,       /* u8  ep_bmAttributes; Interrupt */
+                    /* u16 ep_wMaxPacketSize; */
+        CCID_MAX_PACKET_SIZE & 0xff, (CCID_MAX_PACKET_SIZE >> 8),
+        0xff,       /* u8  ep_bInterval; */
+
+        /* Bulk-In endpoint */
+        0x07,       /* u8  ep_bLength; */
+                    /* u8  ep_bDescriptorType; Endpoint */
+        USB_DT_ENDPOINT,
+                    /* u8  ep_bEndpointAddress; IN Endpoint 2 */
+        0x80 | CCID_BULK_IN_EP,
+        0x02,       /* u8  ep_bmAttributes; Bulk */
+        0x40, 0x00, /* u16 ep_wMaxPacketSize; */
+        0x00,       /* u8  ep_bInterval; */
+
+        /* Bulk-Out endpoint */
+        0x07,       /* u8  ep_bLength; */
+                    /* u8  ep_bDescriptorType; Endpoint */
+        USB_DT_ENDPOINT,
+                    /* u8  ep_bEndpointAddress; OUT Endpoint 3 */
+        CCID_BULK_OUT_EP,
+        0x02,       /* u8  ep_bmAttributes; Bulk */
+        0x40, 0x00, /* u16 ep_wMaxPacketSize; */
+        0x00,       /* u8  ep_bInterval; */
+
+};
+
+static bool ccid_has_pending_answers(USBCCIDState *s)
+{
+    return s->pending_answers_num > 0;
+}
+
+static void ccid_clear_pending_answers(USBCCIDState *s)
+{
+    s->pending_answers_num = 0;
+    s->pending_answers_start = 0;
+    s->pending_answers_end = 0;
+}
+
+static void ccid_print_pending_answers(USBCCIDState *s)
+{
+    Answer *answer;
+    int i, count;
+
+    DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
+    if (!ccid_has_pending_answers(s)) {
+        DPRINTF(s, D_VERBOSE, " empty\n");
+        return;
+    }
+    for (i = s->pending_answers_start, count = s->pending_answers_num ;
+         count > 0; count--, i++) {
+        answer = &s->pending_answers[i % PENDING_ANSWERS_NUM];
+        if (count == 1) {
+            DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
+        } else {
+            DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
+        }
+    }
+}
+
+static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
+{
+    Answer *answer;
+
+    assert(s->pending_answers_num < PENDING_ANSWERS_NUM);
+    s->pending_answers_num++;
+    answer =
+        &s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
+    answer->slot = hdr->bSlot;
+    answer->seq = hdr->bSeq;
+    ccid_print_pending_answers(s);
+}
+
+static void ccid_remove_pending_answer(USBCCIDState *s,
+    uint8_t *slot, uint8_t *seq)
+{
+    Answer *answer;
+
+    assert(s->pending_answers_num > 0);
+    s->pending_answers_num--;
+    answer =
+        &s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
+    *slot = answer->slot;
+    *seq = answer->seq;
+    ccid_print_pending_answers(s);
+}
+
+static void ccid_bulk_in_clear(USBCCIDState *s)
+{
+    s->bulk_in_pending_start = 0;
+    s->bulk_in_pending_end = 0;
+    s->bulk_in_pending_num = 0;
+}
+
+static void ccid_bulk_in_release(USBCCIDState *s)
+{
+    assert(s->current_bulk_in != NULL);
+    s->current_bulk_in->pos = 0;
+    s->current_bulk_in = NULL;
+}
+
+static void ccid_bulk_in_get(USBCCIDState *s)
+{
+    if (s->current_bulk_in != NULL || s->bulk_in_pending_num == 0) {
+        return;
+    }
+    assert(s->bulk_in_pending_num > 0);
+    s->bulk_in_pending_num--;
+    s->current_bulk_in =
+        &s->bulk_in_pending[(s->bulk_in_pending_start++) % BULK_IN_PENDING_NUM];
+}
+
+static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
+{
+    BulkIn *bulk_in;
+
+    DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
+
+    /* look for an existing element */
+    if (len > BULK_IN_BUF_SIZE) {
+        DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). "
+                           "discarding message.\n",
+                           __func__, len, BULK_IN_BUF_SIZE);
+        return NULL;
+    }
+    if (s->bulk_in_pending_num >= BULK_IN_PENDING_NUM) {
+        DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. "
+                           "discarding message.\n", __func__);
+        return NULL;
+    }
+    bulk_in =
+        &s->bulk_in_pending[(s->bulk_in_pending_end++) % BULK_IN_PENDING_NUM];
+    s->bulk_in_pending_num++;
+    bulk_in->len = len;
+    return bulk_in->data;
+}
+
+static void ccid_reset(USBCCIDState *s)
+{
+    ccid_bulk_in_clear(s);
+    ccid_clear_pending_answers(s);
+}
+
+static void ccid_detach(USBCCIDState *s)
+{
+    ccid_reset(s);
+}
+
+static void ccid_handle_reset(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    DPRINTF(s, 1, "Reset\n");
+
+    ccid_reset(s);
+}
+
+static int ccid_handle_control(USBDevice *dev, int request, int value,
+                                  int index, int length, uint8_t *data)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    int ret = 0;
+
+    DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+    switch (request) {
+    case DeviceRequest | USB_REQ_GET_STATUS:
+        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
+            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
+        data[1] = 0x00;
+        ret = 2;
+        break;
+    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 0;
+        } else {
+            goto fail;
+        }
+        ret = 0;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 1;
+        } else {
+            goto fail;
+        }
+        ret = 0;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        dev->addr = value;
+        ret = 0;
+        break;
+    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+        switch (value >> 8) {
+        case USB_DT_DEVICE:
+            memcpy(data, qemu_ccid_dev_descriptor,
+                   sizeof(qemu_ccid_dev_descriptor));
+            ret = sizeof(qemu_ccid_dev_descriptor);
+            break;
+        case USB_DT_CONFIG:
+            memcpy(data, qemu_ccid_config_descriptor,
+                   sizeof(qemu_ccid_config_descriptor));
+            ret = sizeof(qemu_ccid_config_descriptor);
+            break;
+        case USB_DT_STRING:
+            switch (value & 0xff) {
+            case 0:
+                /* language ids */
+                data[0] = 4;
+                data[1] = 3;
+                data[2] = 0x09;
+                data[3] = 0x04;
+                ret = 4;
+                break;
+            case 1:
+                /* vendor description */
+                ret = set_usb_string(data, CCID_VENDOR_DESCRIPTION);
+                break;
+            case 2:
+                /* product description */
+                ret = set_usb_string(data, CCID_PRODUCT_DESCRIPTION);
+                break;
+            case 3:
+                /* serial number */
+                ret = set_usb_string(data, CCID_SERIAL_NUMBER_STRING);
+                break;
+            case 4:
+                /* interface name */
+                ret = set_usb_string(data, CCID_INTERFACE_NAME);
+                break;
+            default:
+                goto fail;
+            }
+            break;
+        default:
+            goto fail;
+        }
+        break;
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        data[0] = 1;
+        ret = 1;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        /* Only one configuration - we just ignore the request */
+        ret = 0;
+        break;
+    case DeviceRequest | USB_REQ_GET_INTERFACE:
+        data[0] = 0;
+        ret = 1;
+        break;
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        ret = 0;
+        break;
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        ret = 0;
+        break;
+
+        /* Class specific requests.  */
+    case InterfaceOutClass | CCID_CONTROL_ABORT:
+        DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+        DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
+        DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
+        ret = USB_RET_STALL;
+        break;
+    default:
+fail:
+        DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
+                request, value);
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static bool ccid_card_inserted(USBCCIDState *s)
+{
+    return s->bmSlotICCState & SLOT_0_STATE_MASK;
+}
+
+static uint8_t ccid_card_status(USBCCIDState *s)
+{
+    return ccid_card_inserted(s)
+            ? (s->powered ?
+                ICC_STATUS_PRESENT_ACTIVE
+              : ICC_STATUS_PRESENT_INACTIVE
+              )
+            : ICC_STATUS_NOT_PRESENT;
+}
+
+static uint8_t ccid_calc_status(USBCCIDState *s)
+{
+    /*
+     * page 55, 6.2.6, calculation of bStatus from bmICCStatus and
+     * bmCommandStatus
+     */
+    uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
+    DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
+    return ret;
+}
+
+static void ccid_reset_error_status(USBCCIDState *s)
+{
+    s->bError = ERROR_CMD_NOT_SUPPORTED;
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+}
+
+static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_SlotStatus *h = ccid_reserve_recv_buf(s, sizeof(CCID_SlotStatus));
+    if (h == NULL) {
+        return;
+    }
+    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus;
+    h->b.hdr.dwLength = 0;
+    h->b.hdr.bSlot = recv->bSlot;
+    h->b.hdr.bSeq = recv->bSeq;
+    h->b.bStatus = ccid_calc_status(s);
+    h->b.bError = s->bError;
+    h->bClockStatus = CLOCK_STATUS_RUNNING;
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_Parameter *h;
+    uint32_t len = s->ulProtocolDataStructureSize;
+
+    h = ccid_reserve_recv_buf(s, sizeof(CCID_Parameter) + len);
+    if (h == NULL) {
+        return;
+    }
+    h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
+    h->b.hdr.dwLength = 0;
+    h->b.hdr.bSlot = recv->bSlot;
+    h->b.hdr.bSeq = recv->bSeq;
+    h->b.bStatus = ccid_calc_status(s);
+    h->b.bError = s->bError;
+    h->bProtocolNum = s->bProtocolNum;
+    memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
+                                  const uint8_t *data, uint32_t len)
+{
+    CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
+
+    if (p == NULL) {
+        return;
+    }
+    p->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock;
+    p->b.hdr.dwLength = cpu_to_le32(len);
+    p->b.hdr.bSlot = slot;
+    p->b.hdr.bSeq = seq;
+    p->b.bStatus = ccid_calc_status(s);
+    p->b.bError = s->bError;
+    if (p->b.bError) {
+        DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
+    }
+    memcpy(p->abData, data, len);
+    ccid_reset_error_status(s);
+}
+
+static void ccid_write_data_block_answer(USBCCIDState *s,
+    const uint8_t *data, uint32_t len)
+{
+    uint8_t seq;
+    uint8_t slot;
+
+    if (!ccid_has_pending_answers(s)) {
+        abort();
+    }
+    ccid_remove_pending_answer(s, &slot, &seq);
+    ccid_write_data_block(s, slot, seq, data, len);
+}
+
+static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
+{
+    const uint8_t *atr = NULL;
+    uint32_t len = 0;
+
+    if (s->card) {
+        atr = s->cardinfo->get_atr(s->card, &len);
+    }
+    ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
+}
+
+static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
+{
+    CCID_SetParameters *ph = (CCID_SetParameters *) recv;
+    uint32_t len = 0;
+    if ((ph->bProtocolNum & 3) == 0) {
+        len = 5;
+    }
+    if ((ph->bProtocolNum & 3) == 1) {
+        len = 7;
+    }
+    if (len == 0) {
+        s->bmCommandStatus = COMMAND_STATUS_FAILED;
+        s->bError = 7; /* Protocol invalid or not supported */
+        return;
+    }
+    s->bProtocolNum = ph->bProtocolNum;
+    memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
+    s->ulProtocolDataStructureSize = len;
+    DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
+}
+
+/*
+ * must be 5 bytes for T=0, 7 bytes for T=1
+ * See page 52
+ */
+static const uint8_t abDefaultProtocolDataStructure[7] = {
+    0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
+
+static void ccid_reset_parameters(USBCCIDState *s)
+{
+   uint32_t len = sizeof(abDefaultProtocolDataStructure);
+
+   s->bProtocolNum = 1; /* T=1 */
+   s->ulProtocolDataStructureSize = len;
+   memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
+}
+
+static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
+{
+    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+    s->bError = error;
+}
+
+/* NOTE: only a single slot is supported (SLOT_0) */
+static void ccid_on_slot_change(USBCCIDState *s, bool full)
+{
+    /* RDR_to_PC_NotifySlotChange, 6.3.1 page 56 */
+    uint8_t current = s->bmSlotICCState;
+    if (full) {
+        s->bmSlotICCState |= SLOT_0_STATE_MASK;
+    } else {
+        s->bmSlotICCState &= ~SLOT_0_STATE_MASK;
+    }
+    if (current != s->bmSlotICCState) {
+        s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
+    }
+    s->notify_slot_change = true;
+}
+
+static void ccid_write_data_block_error(
+    USBCCIDState *s, uint8_t slot, uint8_t seq)
+{
+    ccid_write_data_block(s, slot, seq, NULL, 0);
+}
+
+static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
+{
+    uint32_t len;
+
+    if (ccid_card_status(s) != ICC_STATUS_PRESENT_ACTIVE) {
+        DPRINTF(s, 1,
+                "usb-ccid: not sending apdu to client, no card connected\n");
+        ccid_write_data_block_error(s, recv->hdr.bSlot, recv->hdr.bSeq);
+        return;
+    }
+    len = le32_to_cpu(recv->hdr.dwLength);
+    DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
+                recv->hdr.bSeq, len);
+    ccid_add_pending_answer(s, (CCID_Header *)recv);
+    if (s->card) {
+        s->cardinfo->apdu_from_guest(s->card, recv->abData, len);
+    } else {
+        DPRINTF(s, D_WARN, "warning: discarded apdu\n");
+    }
+}
+
+/*
+ * Handle a single USB_TOKEN_OUT, return value returned to guest.
+ * Return value:
+ *  0             - all ok
+ *  USB_RET_STALL - failed to handle packet
+ */
+static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+{
+    CCID_Header *ccid_header;
+
+    if (p->len + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
+        return USB_RET_STALL;
+    }
+    ccid_header = (CCID_Header *)s->bulk_out_data;
+    memcpy(s->bulk_out_data + s->bulk_out_pos, p->data, p->len);
+    s->bulk_out_pos += p->len;
+    if (p->len == CCID_MAX_PACKET_SIZE) {
+        DPRINTF(s, D_VERBOSE,
+            "usb-ccid: bulk_in: expecting more packets (%d/%d)\n",
+            p->len, ccid_header->dwLength);
+        return 0;
+    }
+    if (s->bulk_out_pos < 10) {
+        DPRINTF(s, 1,
+                "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
+                __func__);
+    } else {
+        DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
+        switch (ccid_header->bMessageType) {
+        case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
+            DPRINTF(s, 1, "PowerOn: %d\n",
+                ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
+            s->powered = true;
+            if (!ccid_card_inserted(s)) {
+                ccid_report_error_failed(s, ERROR_ICC_MUTE);
+            }
+            /* atr is written regardless of error. */
+            ccid_write_data_block_atr(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
+            DPRINTF(s, 1, "PowerOff\n");
+            ccid_reset_error_status(s);
+            s->powered = false;
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
+            ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
+            ccid_reset_error_status(s);
+            ccid_set_parameters(s, ccid_header);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
+            ccid_reset_error_status(s);
+            ccid_reset_parameters(s);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
+            ccid_reset_error_status(s);
+            ccid_write_parameters(s, ccid_header);
+            break;
+        default:
+            DPRINTF(s, 1,
+                "handle_data: ERROR: unhandled message type %Xh\n",
+                ccid_header->bMessageType);
+            /*
+             * The caller is expecting the device to respond, tell it we
+             * don't support the operation.
+             */
+            ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
+            ccid_write_slot_status(s, ccid_header);
+            break;
+        }
+    }
+    s->bulk_out_pos = 0;
+    return 0;
+}
+
+static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, uint8_t *data, int len)
+{
+    int ret = 0;
+
+    assert(len > 0);
+    ccid_bulk_in_get(s);
+    if (s->current_bulk_in != NULL) {
+        ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos, len);
+        memcpy(data, s->current_bulk_in->data + s->current_bulk_in->pos, ret);
+        s->current_bulk_in->pos += ret;
+        if (s->current_bulk_in->pos == s->current_bulk_in->len) {
+            ccid_bulk_in_release(s);
+        }
+    } else {
+        /* return when device has no data - usb 2.0 spec Table 8-4 */
+        ret = USB_RET_NAK;
+    }
+    if (ret > 0) {
+        DPRINTF(s, D_MORE_INFO,
+                "%s: %d/%d req/act to guest (BULK_IN)\n", __func__, len, ret);
+    }
+    if (ret != USB_RET_NAK && ret < len) {
+        DPRINTF(s, 1,
+            "%s: returning short (EREMOTEIO) %d < %d\n", __func__, ret, len);
+    }
+    return ret;
+}
+
+static int ccid_handle_data(USBDevice *dev, USBPacket *p)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    int ret = 0;
+    uint8_t *data = p->data;
+    int len = p->len;
+
+    switch (p->pid) {
+    case USB_TOKEN_OUT:
+        ret = ccid_handle_bulk_out(s, p);
+        break;
+
+    case USB_TOKEN_IN:
+        switch (p->devep & 0xf) {
+        case CCID_BULK_IN_EP:
+            if (!len) {
+                ret = USB_RET_NAK;
+            } else {
+                ret = ccid_bulk_in_copy_to_guest(s, data, len);
+            }
+            break;
+        case CCID_INT_IN_EP:
+            if (s->notify_slot_change) {
+                /* page 56, RDR_to_PC_NotifySlotChange */
+                data[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
+                data[1] = s->bmSlotICCState;
+                ret = 2;
+                s->notify_slot_change = false;
+                s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
+                DPRINTF(s, D_INFO,
+                        "handle_data: int_in: notify_slot_change %X, "
+                        "requested len %d\n",
+                        s->bmSlotICCState, len);
+            }
+            break;
+        default:
+            DPRINTF(s, 1, "Bad endpoint\n");
+            break;
+        }
+        break;
+    default:
+        DPRINTF(s, 1, "Bad token\n");
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void ccid_handle_destroy(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    ccid_bulk_in_clear(s);
+}
+
+static void ccid_flush_pending_answers(USBCCIDState *s)
+{
+    while (ccid_has_pending_answers(s)) {
+        ccid_write_data_block_answer(s, NULL, 0);
+    }
+}
+
+static Answer *ccid_peek_next_answer(USBCCIDState *s)
+{
+    return s->pending_answers_num == 0
+        ? NULL
+        : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
+}
+
+static void ccid_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
+{
+    CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
+    CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev->info);
+
+    if (info->print) {
+        info->print(mon, card, indent);
+    }
+}
+
+struct CCIDBus {
+    BusState qbus;
+};
+
+static struct BusInfo ccid_bus_info = {
+    .name = "ccid-bus",
+    .size = sizeof(CCIDBus),
+    .print_dev = ccid_bus_dev_print,
+    .props = (Property[]) {
+        DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static CCIDBus *ccid_bus_new(DeviceState *dev)
+{
+    CCIDBus *bus;
+
+    bus = FROM_QBUS(CCIDBus, qbus_create(&ccid_bus_info, dev, NULL));
+    bus->qbus.allow_hotplug = 1;
+
+    return bus;
+}
+
+void ccid_card_send_apdu_to_guest(CCIDCardState *card,
+                                  uint8_t *apdu, uint32_t len)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
+                                card->qdev.parent_bus->parent);
+    Answer *answer;
+
+    if (!ccid_has_pending_answers(s)) {
+        DPRINTF(s, 1, "CCID ERROR: got an APDU without pending answers\n");
+        return;
+    }
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+    answer = ccid_peek_next_answer(s);
+    if (answer == NULL) {
+        abort();
+    }
+    DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
+        len, answer->seq, answer->slot);
+    ccid_write_data_block_answer(s, apdu, len);
+}
+
+void ccid_card_card_removed(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    ccid_on_slot_change(s, false);
+    ccid_flush_pending_answers(s);
+    ccid_reset(s);
+}
+
+int ccid_card_ccid_attach(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    DPRINTF(s, 1, "CCID Attach\n");
+    if (s->migration_state == MIGRATION_MIGRATED) {
+        s->migration_state = MIGRATION_NONE;
+    }
+    return 0;
+}
+
+void ccid_card_ccid_detach(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    DPRINTF(s, 1, "CCID Detach\n");
+    if (ccid_card_inserted(s)) {
+        ccid_on_slot_change(s, false);
+    }
+    ccid_detach(s);
+}
+
+void ccid_card_card_error(CCIDCardState *card, uint64_t error)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+    s->last_answer_error = error;
+    DPRINTF(s, 1, "VSC_Error: %lX\n", s->last_answer_error);
+    /* TODO: these error's should be more verbose and propogated to the guest.*/
+    /*
+     * We flush all pending answers on CardRemove message in ccid-card-passthru,
+     * so check that first to not trigger abort
+     */
+    if (ccid_has_pending_answers(s)) {
+        ccid_write_data_block_answer(s, NULL, 0);
+    }
+}
+
+void ccid_card_card_inserted(CCIDCardState *card)
+{
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+    ccid_flush_pending_answers(s);
+    ccid_on_slot_change(s, true);
+}
+
+static int ccid_card_exit(DeviceState *qdev)
+{
+    int ret = 0;
+    CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
+    CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev->info);
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+
+    if (ccid_card_inserted(s)) {
+        ccid_card_card_removed(card);
+    }
+    if (info->exitfn) {
+        ret = info->exitfn(card);
+    }
+    s->card = NULL;
+    s->cardinfo = NULL;
+    return ret;
+}
+
+static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
+{
+    CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
+    CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, base);
+    USBCCIDState *s =
+        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    int ret = 0;
+
+    if (card->slot != 0) {
+        error_report("Warning: usb-ccid supports one slot, can't add %d",
+                card->slot);
+        return -1;
+    }
+    if (s->card != NULL) {
+        error_report("Warning: usb-ccid card already full, not adding\n");
+        return -1;
+    }
+    ret = info->initfn ? info->initfn(card) : ret;
+    if (ret == 0) {
+        s->card = card;
+        s->cardinfo = info;
+    }
+    return ret;
+}
+
+void ccid_card_qdev_register(CCIDCardInfo *card)
+{
+    card->qdev.bus_info = &ccid_bus_info;
+    card->qdev.init = ccid_card_init;
+    card->qdev.exit = ccid_card_exit;
+    qdev_register(&card->qdev);
+}
+
+static int ccid_initfn(USBDevice *dev)
+{
+    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+
+    s->bus = ccid_bus_new(&dev->qdev);
+    s->card = NULL;
+    s->cardinfo = NULL;
+    s->migration_state = MIGRATION_NONE;
+    s->migration_target_ip = 0;
+    s->migration_target_port = 0;
+    s->dev.speed = USB_SPEED_FULL;
+    s->notify_slot_change = false;
+    s->powered = true;
+    s->pending_answers_num = 0;
+    s->last_answer_error = 0;
+    s->bulk_in_pending_start = 0;
+    s->bulk_in_pending_end = 0;
+    s->current_bulk_in = NULL;
+    ccid_reset_error_status(s);
+    s->bulk_out_pos = 0;
+    ccid_reset_parameters(s);
+    ccid_reset(s);
+    return 0;
+}
+
+static int ccid_post_load(void *opaque, int version_id)
+{
+    USBCCIDState *s = opaque;
+
+    /*
+     * This must be done after usb_device_attach, which sets state to ATTACHED,
+     * while it must be DEFAULT in order to accept packets (like it is after
+     * reset, but reset will reset our addr and call our reset handler which
+     * may change state, and we don't want to do that when migrating).
+     */
+    s->dev.state = s->state_vmstate;
+    return 0;
+}
+
+static void ccid_pre_save(void *opaque)
+{
+    USBCCIDState *s = opaque;
+
+    s->state_vmstate = s->dev.state;
+    if (s->dev.attached) {
+        /*
+         * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
+         * erronous detach.
+         */
+        s->migration_state = MIGRATION_MIGRATED;
+    }
+}
+
+static VMStateDescription bulk_in_vmstate = {
+    .name = "CCID BulkIn state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_BUFFER(data, BulkIn),
+        VMSTATE_UINT32(len, BulkIn),
+        VMSTATE_UINT32(pos, BulkIn),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription answer_vmstate = {
+    .name = "CCID Answer state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(slot, Answer),
+        VMSTATE_UINT8(seq, Answer),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription usb_device_vmstate = {
+    .name = "usb_device",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(addr, USBDevice),
+        VMSTATE_BUFFER(setup_buf, USBDevice),
+        VMSTATE_BUFFER(data_buf, USBDevice),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static VMStateDescription ccid_vmstate = {
+    .name = CCID_DEV_NAME,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = ccid_post_load,
+    .pre_save = ccid_pre_save,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
+        VMSTATE_UINT8(debug, USBCCIDState),
+        VMSTATE_BUFFER(bulk_out_data, USBCCIDState),
+        VMSTATE_UINT32(bulk_out_pos, USBCCIDState),
+        VMSTATE_UINT8(bmSlotICCState, USBCCIDState),
+        VMSTATE_UINT8(powered, USBCCIDState),
+        VMSTATE_UINT8(notify_slot_change, USBCCIDState),
+        VMSTATE_UINT64(last_answer_error, USBCCIDState),
+        VMSTATE_UINT8(bError, USBCCIDState),
+        VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
+        VMSTATE_UINT8(bProtocolNum, USBCCIDState),
+        VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
+        VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
+        VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
+                       BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
+        VMSTATE_UINT32(bulk_in_pending_start, USBCCIDState),
+        VMSTATE_UINT32(bulk_in_pending_end, USBCCIDState),
+        VMSTATE_STRUCT_ARRAY(pending_answers, USBCCIDState,
+                        PENDING_ANSWERS_NUM, 1, answer_vmstate, Answer),
+        VMSTATE_UINT32(pending_answers_num, USBCCIDState),
+        VMSTATE_UINT8(migration_state, USBCCIDState),
+        VMSTATE_UINT32(state_vmstate, USBCCIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static struct USBDeviceInfo ccid_info = {
+    .product_desc   = "QEMU USB CCID",
+    .qdev.name      = CCID_DEV_NAME,
+    .qdev.desc      = "CCID Rev 1.1 smartcard reader",
+    .qdev.size      = sizeof(USBCCIDState),
+    .init           = ccid_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = ccid_handle_reset,
+    .handle_control = ccid_handle_control,
+    .handle_data    = ccid_handle_data,
+    .handle_destroy = ccid_handle_destroy,
+    .usbdevice_name = "ccid",
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .qdev.vmsd      = &ccid_vmstate,
+};
+
+static void ccid_register_devices(void)
+{
+    usb_qdev_register(&ccid_info);
+}
+device_init(ccid_register_devices)
commit 65097429ae1929c0c2da5577f6510a1eac82bd7a
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 15 00:18:02 2011 +0200

    qemu-thread.h: include inttypes.h
    
    qemu-thread.h relies on uint64_t being defined, but doesn't include
    inttypes.h explicitly. This makes it easier to use it from vscclient (part
    of libcacard).

diff --git a/qemu-thread.h b/qemu-thread.h
index edc7ab6..0a73d50 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -1,6 +1,8 @@
 #ifndef __QEMU_THREAD_H
 #define __QEMU_THREAD_H 1
 
+#include <inttypes.h>
+
 typedef struct QemuMutex QemuMutex;
 typedef struct QemuCond QemuCond;
 typedef struct QemuThread QemuThread;
commit f20600f213d4cae223660b4ca2eddf139f5e681e
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Mar 16 17:30:21 2011 +0200

    trace: move trace objects from Makefile to Makefile.objs

diff --git a/Makefile b/Makefile
index 989622b..1e3f51a 100644
--- a/Makefile
+++ b/Makefile
@@ -112,38 +112,6 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
 
-ifeq ($(TRACE_BACKEND),dtrace)
-trace.h: trace.h-timestamp trace-dtrace.h
-else
-trace.h: trace.h-timestamp
-endif
-trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
-	@cmp -s $@ trace.h || cp $@ trace.h
-
-trace.c: trace.c-timestamp
-trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
-	@cmp -s $@ trace.c || cp $@ trace.c
-
-trace.o: trace.c $(GENERATED_HEADERS)
-
-trace-dtrace.h: trace-dtrace.dtrace
-	$(call quiet-command,dtrace -o $@ -h -s $<, "  GEN   trace-dtrace.h")
-
-# Normal practice is to name DTrace probe file with a '.d' extension
-# but that gets picked up by QEMU's Makefile as an external dependancy
-# rule file. So we use '.dtrace' instead
-trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
-trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
-	@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
-
-trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
-	$(call quiet-command,dtrace -o $@ -G -s $<, "  GEN trace-dtrace.o")
-
-simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
-
 version.o: $(SRC_PATH)/version.rc config-host.mak
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 
diff --git a/Makefile.objs b/Makefile.objs
index 42301fd..d906a8e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -310,6 +310,38 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
 # trace
 
 ifeq ($(TRACE_BACKEND),dtrace)
+trace.h: trace.h-timestamp trace-dtrace.h
+else
+trace.h: trace.h-timestamp
+endif
+trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
+	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+	@cmp -s $@ trace.h || cp $@ trace.h
+
+trace.c: trace.c-timestamp
+trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
+	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+	@cmp -s $@ trace.c || cp $@ trace.c
+
+trace.o: trace.c $(GENERATED_HEADERS)
+
+trace-dtrace.h: trace-dtrace.dtrace
+	$(call quiet-command,dtrace -o $@ -h -s $<, "  GEN   trace-dtrace.h")
+
+# Normal practice is to name DTrace probe file with a '.d' extension
+# but that gets picked up by QEMU's Makefile as an external dependancy
+# rule file. So we use '.dtrace' instead
+trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
+trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
+	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
+	@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
+
+trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
+	$(call quiet-command,dtrace -o $@ -G -s $<, "  GEN trace-dtrace.o")
+
+simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
+
+ifeq ($(TRACE_BACKEND),dtrace)
 trace-obj-y = trace-dtrace.o
 else
 trace-obj-y = trace.o
commit f68b9d672b90dedc79aeb9b44607f484dbe46a6b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 22 18:39:40 2011 +0000

    net: Improve the warnings for dubious command line option combinations
    
    Improve the warnings we give if the user specified a combination of -net
    options which don't make much sense:
     * Don't warn about anything if the config is the implicit default
       "-net user -net nic" rather than one specified by the user (this will
       only kick in for boards with no NIC or if CONFIG_SLIRP is not set)
     * Diagnose the case where the user asked for NICs which the board
       didn't instantiate (for example where the user asked for two NICs
       but the board only supports one)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index b2dfaa8..8d6a555 100644
--- a/net.c
+++ b/net.c
@@ -1305,6 +1305,22 @@ void net_check_clients(void)
 {
     VLANState *vlan;
     VLANClientState *vc;
+    int seen_nics = 0;
+
+    /* Don't warn about the default network setup that you get if
+     * no command line -net options are specified. There are two
+     * cases that we would otherwise complain about:
+     * (1) board doesn't support a NIC but the implicit "-net nic"
+     * requested one; we'd otherwise complain about more NICs being
+     * specified than we support, and also that the vlan set up by
+     * the implicit "-net user" didn't have any NICs connected to it
+     * (2) CONFIG_SLIRP not set: we'd otherwise complain about the
+     * implicit "-net nic" setting up a nic that wasn't connected to
+     * anything.
+     */
+    if (default_net) {
+        return;
+    }
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         int has_nic = 0, has_host_dev = 0;
@@ -1312,6 +1328,7 @@ void net_check_clients(void)
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             switch (vc->info->type) {
             case NET_CLIENT_TYPE_NIC:
+                seen_nics++;
                 has_nic = 1;
                 break;
             case NET_CLIENT_TYPE_SLIRP:
@@ -1331,12 +1348,26 @@ void net_check_clients(void)
                     vlan->id);
     }
     QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (vc->info->type == NET_CLIENT_TYPE_NIC) {
+            seen_nics++;
+        }
         if (!vc->peer) {
             fprintf(stderr, "Warning: %s %s has no peer\n",
                     vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
                     vc->name);
         }
     }
+    if (seen_nics != nb_nics) {
+        /* Number of NICs requested by user on command line doesn't match
+         * the number the model actually registered with us.
+         * This will generally only happen for models of embedded boards
+         * with no PCI bus or similar. PCI based machines can instantiate
+         * all requested NICs as PCI devices but usually embedded boards
+         * only have a single NIC.
+         */
+        fprintf(stderr, "Warning: more nics requested than this machine "
+                "supports; some have been ignored\n");
+    }
 }
 
 static int net_init_client(QemuOpts *opts, void *dummy)
commit e6b3c8ca0222f6633516c0461a713e7bddc4f076
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 22 18:21:58 2011 +0000

    hw/versatilepb, realview: Fix condition for instantiation of onboard NIC
    
    Correct the condition determining whether we instantiate the onboard
    NIC or a PCI card NIC on VersatilePB and Realview boards. This was broken
    in two ways:
     (1) if the user asked for two default NICs ("-net nic -net nic") we would
    crash trying to strcmp() a NULL pointer
     (2) if the user asked for two NICs explicitly of the same model as the
    onboard NIC (eg "-net nic,model=smc91c111 -net nic,model=smc91c111")
    we would try to instantiate two onboard NICs at the same address.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/realview.c b/hw/realview.c
index a67861e..96fb9da 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -288,8 +288,8 @@ static void realview_init(ram_addr_t ram_size,
     for(n = 0; n < nb_nics; n++) {
         nd = &nd_table[n];
 
-        if ((!nd->model && !done_nic)
-            || strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0) {
+        if (!done_nic && (!nd->model ||
+                    strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
             if (is_pb) {
                 lan9118_init(nd, 0x4e000000, pic[28]);
             } else {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 9f1bfcf..46b6a3f 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -223,7 +223,7 @@ static void versatile_init(ram_addr_t ram_size,
     for(n = 0; n < nb_nics; n++) {
         nd = &nd_table[n];
 
-        if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {
+        if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
             smc91c111_init(nd, 0x10010000, sic[25]);
             done_smc = 1;
         } else {
commit 366c9332450caace5843c17806ba4879bf2d005c
Author: Michael Brown <mcb30 at ipxe.org>
Date:   Tue Mar 15 10:47:22 2011 -0600

    pcnet: Fix sign extension: make ipxe work with >2G RAM
    
    The problem is with definitions in hw/pcnet.c such as:
    
      #define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
    
    "(S)->csr[29]" is a uint16_t, but "(S)->csr[29] << 16" gets promoted to
    int, so the overall CSR_CRDA(s) is a (signed) int rather than a uint32_t.
    
    This then gets assigned to a uint64_t using
    
      target_phys_addr_t crda = CSR_CRDA(s);
    
    so when (S)->csr[29] has the high bit set, we end up with
    crda=0xffffffffxxxxxxxx.
    
    From: Michael Brown <mcb30 at ipxe.org>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pcnet.c b/hw/pcnet.c
index 82ccbbd..cf16fd4 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -113,23 +113,23 @@ struct qemu_ether_header {
 #define CSR_XMTRL(S)     ((S)->csr[78])
 #define CSR_MISSC(S)     ((S)->csr[112])
 
-#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
-#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
-#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
-#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
-#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
-#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
-#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
-#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
-#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
-#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
-#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
-#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
-#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
-#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
+#define CSR_IADR(S)      ((S)->csr[ 1] | ((uint32_t)(S)->csr[ 2] << 16))
+#define CSR_CRBA(S)      ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16))
+#define CSR_CXBA(S)      ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16))
+#define CSR_NRBA(S)      ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16))
+#define CSR_BADR(S)      ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16))
+#define CSR_NRDA(S)      ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16))
+#define CSR_CRDA(S)      ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16))
+#define CSR_BADX(S)      ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16))
+#define CSR_NXDA(S)      ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16))
+#define CSR_CXDA(S)      ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16))
+#define CSR_NNRD(S)      ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16))
+#define CSR_NNXD(S)      ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16))
+#define CSR_PXDA(S)      ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16))
+#define CSR_NXBA(S)      ((S)->csr[64] | ((uint32_t)(S)->csr[65] << 16))
 
 #define PHYSADDR(S,A) \
-  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
 
 struct pcnet_initblk16 {
     uint16_t mode;
commit e318a60b94b152c1e80125861a8917ae177d845e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 15 16:26:52 2011 +0000

    target-arm: Don't leak TCG temp for UNDEFs in Neon load/store space
    
    Move the allocation and freeing of the TCG temp used for the address for
    Neon load/store instructions so that we don't allocate the temporary
    until we've done enough decoding to know that the instruction is not
    an UNDEF pattern; this avoids leaking the TCG temp in these cases.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 1dfd482..39512bc 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3810,7 +3810,6 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
     rn = (insn >> 16) & 0xf;
     rm = insn & 0xf;
     load = (insn & (1 << 21)) != 0;
-    addr = tcg_temp_new_i32();
     if ((insn & (1 << 23)) == 0) {
         /* Load store all elements.  */
         op = (insn >> 8) & 0xf;
@@ -3822,6 +3821,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
         spacing = neon_ls_element_type[op].spacing;
         if (size == 3 && (interleave | spacing) != 1)
             return 1;
+        addr = tcg_temp_new_i32();
         load_reg_var(s, addr, rn);
         stride = (1 << size) * interleave;
         for (reg = 0; reg < nregs; reg++) {
@@ -3907,6 +3907,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
             }
             rd += spacing;
         }
+        tcg_temp_free_i32(addr);
         stride = nregs * 8;
     } else {
         size = (insn >> 10) & 3;
@@ -3932,6 +3933,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
             if (nregs == 3 && a == 1) {
                 return 1;
             }
+            addr = tcg_temp_new_i32();
             load_reg_var(s, addr, rn);
             if (nregs == 1) {
                 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
@@ -3955,6 +3957,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     rd += stride;
                 }
             }
+            tcg_temp_free_i32(addr);
             stride = (1 << size) * nregs;
         } else {
             /* Single element.  */
@@ -3976,6 +3979,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 abort();
             }
             nregs = ((insn >> 8) & 3) + 1;
+            addr = tcg_temp_new_i32();
             load_reg_var(s, addr, rn);
             for (reg = 0; reg < nregs; reg++) {
                 if (load) {
@@ -4017,10 +4021,10 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 rd += stride;
                 tcg_gen_addi_i32(addr, addr, 1 << size);
             }
+            tcg_temp_free_i32(addr);
             stride = nregs * (1 << size);
         }
     }
-    tcg_temp_free_i32(addr);
     if (rm != 15) {
         TCGv base;
 
commit 8e18cde30b06d2e7411bf38091c4e30602f85cdd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 15 16:26:51 2011 +0000

    target-arm: Fix VLD of single element to all lanes
    
    Fix several bugs in VLD of single element to all lanes:
    
    The "single element to all lanes" form of VLD1 differs from those for
    VLD2, VLD3 and VLD4 in that bit 5 indicates whether the loaded element
    should be written to one or two Dregs (rather than being a register
    stride). Handle this by special-casing VLD1 rather than trying to
    have one loop which deals with both VLD1 and 2/3/4.
    
    Handle VLD4.32 with 16 byte alignment specified, rather than UNDEFfing.
    
    UNDEF for the invalid size and alignment combinations.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index f69912f..1dfd482 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2648,6 +2648,28 @@ static void gen_neon_dup_high16(TCGv var)
     tcg_temp_free_i32(tmp);
 }
 
+static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
+{
+    /* Load a single Neon element and replicate into a 32 bit TCG reg */
+    TCGv tmp;
+    switch (size) {
+    case 0:
+        tmp = gen_ld8u(addr, IS_USER(s));
+        gen_neon_dup_u8(tmp, 0);
+        break;
+    case 1:
+        tmp = gen_ld16u(addr, IS_USER(s));
+        gen_neon_dup_low16(tmp);
+        break;
+    case 2:
+        tmp = gen_ld32(addr, IS_USER(s));
+        break;
+    default: /* Avoid compiler warnings.  */
+        abort();
+    }
+    return tmp;
+}
+
 /* Disassemble a VFP instruction.  Returns nonzero if an error occured
    (ie. an undefined instruction).  */
 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
@@ -3890,36 +3912,48 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
         size = (insn >> 10) & 3;
         if (size == 3) {
             /* Load single element to all lanes.  */
-            if (!load)
+            int a = (insn >> 4) & 1;
+            if (!load) {
                 return 1;
+            }
             size = (insn >> 6) & 3;
             nregs = ((insn >> 8) & 3) + 1;
-            stride = (insn & (1 << 5)) ? 2 : 1;
-            load_reg_var(s, addr, rn);
-            for (reg = 0; reg < nregs; reg++) {
-                switch (size) {
-                case 0:
-                    tmp = gen_ld8u(addr, IS_USER(s));
-                    gen_neon_dup_u8(tmp, 0);
-                    break;
-                case 1:
-                    tmp = gen_ld16u(addr, IS_USER(s));
-                    gen_neon_dup_low16(tmp);
-                    break;
-                case 2:
-                    tmp = gen_ld32(addr, IS_USER(s));
-                    break;
-                case 3:
+
+            if (size == 3) {
+                if (nregs != 4 || a == 0) {
                     return 1;
-                default: /* Avoid compiler warnings.  */
-                    abort();
                 }
-                tcg_gen_addi_i32(addr, addr, 1 << size);
-                tmp2 = tcg_temp_new_i32();
-                tcg_gen_mov_i32(tmp2, tmp);
-                neon_store_reg(rd, 0, tmp2);
-                neon_store_reg(rd, 1, tmp);
-                rd += stride;
+                /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
+                size = 2;
+            }
+            if (nregs == 1 && a == 1 && size == 0) {
+                return 1;
+            }
+            if (nregs == 3 && a == 1) {
+                return 1;
+            }
+            load_reg_var(s, addr, rn);
+            if (nregs == 1) {
+                /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
+                tmp = gen_load_and_replicate(s, addr, size);
+                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
+                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
+                if (insn & (1 << 5)) {
+                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
+                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
+                }
+                tcg_temp_free_i32(tmp);
+            } else {
+                /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
+                stride = (insn & (1 << 5)) ? 2 : 1;
+                for (reg = 0; reg < nregs; reg++) {
+                    tmp = gen_load_and_replicate(s, addr, size);
+                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
+                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
+                    tcg_temp_free_i32(tmp);
+                    tcg_gen_addi_i32(addr, addr, 1 << size);
+                    rd += stride;
+                }
             }
             stride = (1 << size) * nregs;
         } else {
commit ac60cc18711a9786af9844d7e3d002276fbd85f3
Author: Tristan Gingold <gingold at adacore.com>
Date:   Tue Mar 15 14:20:54 2011 +0100

    Fix net_check_clients warnings: make it per vlan.
    
    Signed-off-by: Tristan Gingold <gingold at adacore.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index ddcca97..b2dfaa8 100644
--- a/net.c
+++ b/net.c
@@ -1305,9 +1305,10 @@ void net_check_clients(void)
 {
     VLANState *vlan;
     VLANClientState *vc;
-    int has_nic = 0, has_host_dev = 0;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
+        int has_nic = 0, has_host_dev = 0;
+
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             switch (vc->info->type) {
             case NET_CLIENT_TYPE_NIC:
commit ee7495d3a9304942ad75f07713b565db25352411
Author: Leszek Grzegorek <leszek.grzegorek at gmail.com>
Date:   Mon Mar 14 10:30:08 2011 +0100

    vnc: added missing name->keysym pairs for Polish national characters
    
    There are no { name, keysym } values in name2keysym[] array for Polish
    national characters so "-k pl" option has no effect.
    
    Signed-off-by: Leszek Grzegorek <leszek.grzegorek at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h
index 55cb87e..df33cfe 100644
--- a/ui/vnc_keysym.h
+++ b/ui/vnc_keysym.h
@@ -202,6 +202,24 @@ static const name2keysym_t name2keysym[]={
 { "ydiaeresis",           0x0ff},
 {"EuroSign", 0x20ac},  /* XK_EuroSign */
 
+/* latin 2 - Polish national characters */
+{ "eogonek",              0x1ea},
+{ "Eogonek",              0x1ca},
+{ "aogonek",              0x1b1},
+{ "Aogonek",              0x1a1},
+{ "sacute",               0x1b6},
+{ "Sacute",               0x1a6},
+{ "lstroke",              0x1b3},
+{ "Lstroke",              0x1a3},
+{ "zabovedot",            0x1bf},
+{ "Zabovedot",            0x1af},
+{ "zacute",               0x1bc},
+{ "Zacute",               0x1ac},
+{ "cacute",               0x1e6},
+{ "Cacute",               0x1c6},
+{ "nacute",               0x1f1},
+{ "Nacute",               0x1d1},
+
     /* modifiers */
 {"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
 {"Control_L", 0xffe3}, /* XK_Control_L */
commit 8cffde7329734c17ee2eeec84944abbf4a0f23f3
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Thu Mar 10 17:03:41 2011 +0300

    get rid of private bitmap functions in block/sheepdog.c, use generic ones
    
    qemu now has generic bitmap functions,
    so don't redefine them in sheepdog.c,
    use common header instead.  A small cleanup.
    
    Here's only one function which is actually
    used in sheepdog and gets replaced with
    a generic one (simplified):
    
    - static inline int test_bit(int nr, const volatile unsigned long *addr)
    + static inline int test_bit(int nr, const unsigned long *addr)
     {
    -  return ((1UL << (nr % BITS_PER_LONG))
                & ((unsigned long*)addr)[nr / BITS_PER_LONG])) != 0;
    +  return 1UL & (addr[nr / BITS_PER_LONG] >> (nr & (BITS_PER_LONG-1)));
     }
    
    The body is equivalent, but the argument is not: there's
    "volatile" in there.  Why it is used for - I'm not sure.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Acked-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index a54e0de..98946d7 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -13,6 +13,7 @@
 #include "qemu-error.h"
 #include "qemu_socket.h"
 #include "block_int.h"
+#include "bitops.h"
 
 #define SD_PROTO_VER 0x01
 
@@ -1829,20 +1830,6 @@ static int sd_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
     return 0;
 }
 
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define BITS_PER_BYTE        8
-#define BITS_TO_LONGS(nr)    DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define DECLARE_BITMAP(name,bits)               \
-    unsigned long name[BITS_TO_LONGS(bits)]
-
-#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
-
-static inline int test_bit(unsigned int nr, const unsigned long *addr)
-{
-    return ((1UL << (nr % BITS_PER_LONG)) &
-            (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
-}
-
 static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 {
     BDRVSheepdogState *s = bs->opaque;
commit 508240c0daecdd62ab46727f37145f2dbb029ff7
Author: Bernhard Kohl <bernhard.kohl at nsn.com>
Date:   Mon Sep 6 04:42:54 2010 +0000

    lsi53c895a: add support for ABORT messages
    
    If these messages are not handled correctly the guest driver may hang.
    
    Always mandatory:
    - ABORT
    - BUS DEVICE RESET
    
    Mandatory if tagged queuing is implemented (which disks usually do):
    - ABORT TAG
    - CLEAR QUEUE
    
    Signed-off-by: Bernhard Kohl <bernhard.kohl at nsn.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 84a4992..e4b51a8 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -853,6 +853,18 @@ static void lsi_do_msgout(LSIState *s)
 {
     uint8_t msg;
     int len;
+    uint32_t current_tag;
+    SCSIDevice *current_dev;
+    lsi_request *p, *p_next;
+    int id;
+
+    if (s->current) {
+        current_tag = s->current->tag;
+    } else {
+        current_tag = s->select_tag;
+    }
+    id = (current_tag >> 8) & 0xf;
+    current_dev = s->bus.devs[id];
 
     DPRINTF("MSG out len=%d\n", s->dbc);
     while (s->dbc) {
@@ -898,6 +910,51 @@ static void lsi_do_msgout(LSIState *s)
             BADF("ORDERED queue not implemented\n");
             s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
             break;
+        case 0x0d:
+            /* The ABORT TAG message clears the current I/O process only. */
+            DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag);
+            current_dev->info->cancel_io(current_dev, current_tag);
+            lsi_disconnect(s);
+            break;
+        case 0x06:
+        case 0x0e:
+        case 0x0c:
+            /* The ABORT message clears all I/O processes for the selecting
+               initiator on the specified logical unit of the target. */
+            if (msg == 0x06) {
+                DPRINTF("MSG: ABORT tag=0x%x\n", current_tag);
+            }
+            /* The CLEAR QUEUE message clears all I/O processes for all
+               initiators on the specified logical unit of the target. */
+            if (msg == 0x0e) {
+                DPRINTF("MSG: CLEAR QUEUE tag=0x%x\n", current_tag);
+            }
+            /* The BUS DEVICE RESET message clears all I/O processes for all
+               initiators on all logical units of the target. */
+            if (msg == 0x0c) {
+                DPRINTF("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag);
+            }
+
+            /* clear the current I/O process */
+            current_dev->info->cancel_io(current_dev, current_tag);
+
+            /* As the current implemented devices scsi_disk and scsi_generic
+               only support one LUN, we don't need to keep track of LUNs.
+               Clearing I/O processes for other initiators could be possible
+               for scsi_generic by sending a SG_SCSI_RESET to the /dev/sgX
+               device, but this is currently not implemented (and seems not
+               to be really necessary). So let's simply clear all queued
+               commands for the current device: */
+            id = current_tag & 0x0000ff00;
+            QTAILQ_FOREACH_SAFE(p, &s->queue, next, p_next) {
+                if ((p->tag & 0x0000ff00) == id) {
+                    current_dev->info->cancel_io(current_dev, p->tag);
+                    QTAILQ_REMOVE(&s->queue, p, next);
+                }
+            }
+
+            lsi_disconnect(s);
+            break;
         default:
             if ((msg & 0x80) == 0) {
                 goto bad;
commit 59df4c11560fb5da9071b5ab5c4607055fbe927a
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Mon Feb 28 10:22:33 2011 +0800

    fix build errors when we enable acpi_piix4 debug
    
    I enable acpi_piix4 debug, and got the following build errors:
    # make
      CC    libhw64/acpi_piix4.o
    cc1: warnings being treated as errors
    /home/wency/source/qemu/hw/acpi_piix4.c: In function ‘pm_ioport_write’:
    /home/wency/source/qemu/hw/acpi_piix4.c:193: error: format ‘%04x’ expects type ‘unsigned int’, but argument 2 has type ‘uint64_t’
    /home/wency/source/qemu/hw/acpi_piix4.c:193: error: format ‘%04x’ expects type ‘unsigned int’, but argument 3 has type ‘uint64_t’
    /home/wency/source/qemu/hw/acpi_piix4.c: In function ‘pm_ioport_read’:
    /home/wency/source/qemu/hw/acpi_piix4.c:219: error: format ‘%04x’ expects type ‘unsigned int’, but argument 2 has type ‘uint64_t’
    make[1]: *** [acpi_piix4.o] Error 1
    make: *** [subdir-libhw64] Error 2
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0b2bc97..74044dd 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -190,7 +190,8 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
     default:
         break;
     }
-    PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val);
+    PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", (unsigned int)addr,
+                  (unsigned int)val);
 }
 
 static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
@@ -216,7 +217,7 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
         val = 0;
         break;
     }
-    PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
+    PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val);
     *data = val;
 }
 
commit 09cec717bfaaaabd4c2789e480626ce70fdab204
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Feb 16 21:15:40 2011 +0100

    ui/sdl: Load optional QEMU icon
    
    Load an optional QEMU icon file. If there is no icon file named
    qemu.bmp in QEMU's default search path, QEMU will run with
    the usual system default icon.
    
    A matching icon file  will be loaded and used by X Windows managers
    or MS Windows while a QEMU instance is running.
    
    SDL requires icon files in 32x32x4 bmp format.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/ui/sdl.c b/ui/sdl.c
index c5bb0a3..dc5c3a1 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -812,6 +812,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     uint8_t data = 0;
     DisplayAllocator *da;
     const SDL_VideoInfo *vi;
+    char *filename;
 
 #if defined(__APPLE__)
     /* always use generic keymaps */
@@ -844,6 +845,18 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     vi = SDL_GetVideoInfo();
     host_format = *(vi->vfmt);
 
+    /* Load a 32x32x4 image. White pixels are transparent. */
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+    if (filename) {
+        SDL_Surface *image = SDL_LoadBMP(filename);
+        if (image) {
+            uint32_t colorkey = SDL_MapRGB(image->format, 255, 255, 255);
+            SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
+            SDL_WM_SetIcon(image, NULL);
+        }
+        qemu_free(filename);
+    }
+
     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
     dcl->dpy_update = sdl_update;
     dcl->dpy_resize = sdl_resize;
commit d818bfc5c34c59e9c6d03b3b9983bb5435967292
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 1 20:04:24 2011 +0200

    pc-bios/spapr-rtas.bin: remove executable flag
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/pc-bios/spapr-rtas.bin b/pc-bios/spapr-rtas.bin
old mode 100755
new mode 100644
commit a9f8ad8f2acdb2398da5d32a5efc19cb0196d79f
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:34 2011 +1100

    Add SLOF-based partition firmware for pSeries machine, allowing more boot options
    
    Currently, the emulated pSeries machine requires the use of the
    -kernel parameter in order to explicitly load a guest kernel.  This
    means booting from the virtual disk, cdrom or network is not possible.
    
    This patch addresses this limitation by inserting a within-partition
    firmware image (derived from the "SLOF" free Open Firmware project).
    If -kernel is not specified, qemu will now load the SLOF image, which
    has access to the qemu boot device list through the device tree, and
    can boot from any of the usual virtual devices.
    
    In order to support the new firmware, an extension to the emulated
    machine/hypervisor is necessary.  Unlike Linux, which expects
    multi-CPU entry to be handled kexec() style, the SLOF firmware expects
    only one CPU to be active at entry, and to use a hypervisor RTAS
    method to enable the other CPUs one by one.
    
    This patch also implements this 'start-cpu' method, so that SLOF can
    start the secondary CPUs and marshal them into the kexec() holding
    pattern ready for entry into the guest OS.  Linux should, and in the
    future might directly use the start-cpu method to enable initially
    disabled CPUs, but for now it does require kexec() entry.
    
    Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: Paul Mackerras <paulus at samba.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/.gitmodules b/.gitmodules
index 5217ce7..44fdd1a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
 [submodule "roms/seabios"]
 	path = roms/seabios
 	url = git://git.qemu.org/seabios.git/
+[submodule "roms/SLOF"]
+	path = roms/SLOF
+	url = git://git.qemu.org/SLOF.git
diff --git a/Makefile b/Makefile
index e0b3fea..989622b 100644
--- a/Makefile
+++ b/Makefile
@@ -214,7 +214,7 @@ pxe-rtl8139.bin pxe-virtio.bin \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin \
 s390-zipl.rom \
-spapr-rtas.bin
+spapr-rtas.bin slof.bin
 else
 BLOBS=
 endif
diff --git a/hw/spapr.c b/hw/spapr.c
index 8767686..1152a25 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -44,6 +44,10 @@
 #define INITRD_LOAD_ADDR        0x02800000
 #define FDT_MAX_SIZE            0x10000
 #define RTAS_MAX_SIZE           0x10000
+#define FW_MAX_SIZE             0x400000
+#define FW_FILE_NAME            "slof.bin"
+
+#define MIN_RAM_SLOF		512UL
 
 #define TIMEBASE_FREQ           512000000ULL
 
@@ -57,6 +61,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                               sPAPREnvironment *spapr,
                               target_phys_addr_t initrd_base,
                               target_phys_addr_t initrd_size,
+                              const char *boot_device,
                               const char *kernel_cmdline,
                               target_phys_addr_t rtas_addr,
                               target_phys_addr_t rtas_size,
@@ -105,6 +110,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                        &start_prop, sizeof(start_prop))));
     _FDT((fdt_property(fdt, "linux,initrd-end",
                        &end_prop, sizeof(end_prop))));
+    _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
 
     _FDT((fdt_end_node(fdt)));
 
@@ -261,7 +267,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     ram_addr_t ram_offset;
     target_phys_addr_t fdt_addr, rtas_addr;
     uint32_t kernel_base, initrd_base;
-    long kernel_size, initrd_size, htab_size, rtas_size;
+    long kernel_size, initrd_size, htab_size, rtas_size, fw_size;
     long pteg_shift = 17;
     int fdt_size;
     char *filename;
@@ -392,13 +398,33 @@ static void ppc_spapr_init(ram_addr_t ram_size,
             initrd_size = 0;
         }
     } else {
-        fprintf(stderr, "pSeries machine needs -kernel for now");
-        exit(1);
+        if (ram_size < (MIN_RAM_SLOF << 20)) {
+            fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
+                    "%ldM guest RAM\n", MIN_RAM_SLOF);
+            exit(1);
+        }
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "slof.bin");
+        fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+        if (fw_size < 0) {
+            hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+            exit(1);
+        }
+        qemu_free(filename);
+        kernel_base = 0x100;
+        initrd_base = 0;
+        initrd_size = 0;
+
+        /* SLOF will startup the secondary CPUs using RTAS,
+           rather than expecting a kexec() style entry */
+        for (i = 0; i < smp_cpus; i++) {
+            envs[i]->halted = 1;
+        }
     }
 
     /* Prepare the device tree */
     fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
-                           initrd_base, initrd_size, kernel_cmdline,
+                           initrd_base, initrd_size,
+                           boot_device, kernel_cmdline,
                            rtas_addr, rtas_size, pteg_shift + 7);
     assert(fdt != NULL);
 
@@ -409,6 +435,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     envs[0]->gpr[3] = fdt_addr;
     envs[0]->gpr[5] = 0;
     envs[0]->hreset_vector = kernel_base;
+    envs[0]->halted = 0;
 }
 
 static QEMUMachine spapr_machine = {
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 7226853..16b6542 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -90,6 +90,81 @@ static void rtas_power_off(sPAPREnvironment *spapr,
     rtas_st(rets, 0, 0);
 }
 
+static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
+                                         uint32_t token, uint32_t nargs,
+                                         target_ulong args,
+                                         uint32_t nret, target_ulong rets)
+{
+    target_ulong id;
+    CPUState *env;
+
+    if (nargs != 1 || nret != 2) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    id = rtas_ld(args, 0);
+    for (env = first_cpu; env; env = env->next_cpu) {
+        if (env->cpu_index != id) {
+            continue;
+        }
+
+        if (env->halted) {
+            rtas_st(rets, 1, 0);
+        } else {
+            rtas_st(rets, 1, 2);
+        }
+
+        rtas_st(rets, 0, 0);
+        return;
+    }
+
+    /* Didn't find a matching cpu */
+    rtas_st(rets, 0, -3);
+}
+
+static void rtas_start_cpu(sPAPREnvironment *spapr,
+                           uint32_t token, uint32_t nargs,
+                           target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+    target_ulong id, start, r3;
+    CPUState *env;
+
+    if (nargs != 3 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    id = rtas_ld(args, 0);
+    start = rtas_ld(args, 1);
+    r3 = rtas_ld(args, 2);
+
+    for (env = first_cpu; env; env = env->next_cpu) {
+        if (env->cpu_index != id) {
+            continue;
+        }
+
+        if (!env->halted) {
+            rtas_st(rets, 0, -1);
+            return;
+        }
+
+        env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+        env->nip = start;
+        env->gpr[3] = r3;
+        env->halted = 0;
+
+        qemu_cpu_kick(env);
+
+        rtas_st(rets, 0, 0);
+        return;
+    }
+
+    /* Didn't find a matching cpu */
+    rtas_st(rets, 0, -3);
+}
+
 static struct rtas_call {
     const char *name;
     spapr_rtas_fn fn;
@@ -196,5 +271,8 @@ static void register_core_rtas(void)
     spapr_rtas_register("display-character", rtas_display_character);
     spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
     spapr_rtas_register("power-off", rtas_power_off);
+    spapr_rtas_register("query-cpu-stopped-state",
+                        rtas_query_cpu_stopped_state);
+    spapr_rtas_register("start-cpu", rtas_start_cpu);
 }
 device_init(register_core_rtas);
diff --git a/pc-bios/README b/pc-bios/README
index 3fc0944..646a31a 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -13,6 +13,11 @@
   The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
   and Sparc64 are built from OpenBIOS SVN revision 1018.
 
+- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
+  implementation for certain IBM POWER hardware.  The sources are at
+  https://github.com/dgibson/SLOF, and the image currently in qemu is
+  built from git tag qemu-slof-20110323.
+
 - The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
 
   e1000 8086:100E
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
new file mode 100644
index 0000000..22c4c7f
Binary files /dev/null and b/pc-bios/slof.bin differ
diff --git a/roms/SLOF b/roms/SLOF
new file mode 160000
index 0000000..d1d6b53
--- /dev/null
+++ b/roms/SLOF
@@ -0,0 +1 @@
+Subproject commit d1d6b53b713a2b7c2c25685268fa932d28a4b4c0
commit ed120055c7f9b26b5707d3ceabbe5a3f06aaf937
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:33 2011 +1100

    Implement PAPR VPA functions for pSeries shared processor partitions
    
    Shared-processor partitions are those where a CPU is time-sliced between
    partitions, rather than being permanently dedicated to a single
    partition.  qemu emulated partitions, since they are just scheduled with
    the qemu user process, behave mostly like shared processor partitions.
    
    In order to better support shared processor partitions (splpar), PAPR
    defines the "VPA" (Virtual Processor Area), a shared memory communication
    channel between the hypervisor and partitions.  There are also two
    additional shared memory communication areas for specialized purposes
    associated with the VPA.
    
    A VPA is not essential for operating an splpar, though it can be necessary
    for obtaining accurate performance measurements in the presence of
    runtime partition switching.
    
    Most importantly, however, the VPA is a prerequisite for PAPR's H_CEDE,
    hypercall, which allows a partition OS to give up it's shared processor
    timeslices to other partitions when idle.
    
    This patch implements the VPA and H_CEDE hypercalls in qemu.  We don't
    implement any of the more advanced statistics which can be communicated
    through the VPA.  However, this is enough to make normal pSeries kernels
    do an effective power-save idle on an emulated pSeries, significantly
    reducing the host load of a qemu emulated pSeries running an idle guest OS.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 3bffaab..8767686 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -68,7 +68,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
     char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
-        "\0hcall-tce\0hcall-vio";
+        "\0hcall-tce\0hcall-vio\0hcall-splpar";
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index a47a97b..f88e1d2 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -4,6 +4,8 @@
 #include "sysemu.h"
 #include "qemu-char.h"
 #include "exec-all.h"
+#include "exec.h"
+#include "helper_regs.h"
 #include "hw/spapr.h"
 
 #define HPTES_PER_GROUP 8
@@ -255,6 +257,192 @@ static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr,
     return H_HARDWARE;
 }
 
+#define FLAGS_REGISTER_VPA         0x0000200000000000ULL
+#define FLAGS_REGISTER_DTL         0x0000400000000000ULL
+#define FLAGS_REGISTER_SLBSHADOW   0x0000600000000000ULL
+#define FLAGS_DEREGISTER_VPA       0x0000a00000000000ULL
+#define FLAGS_DEREGISTER_DTL       0x0000c00000000000ULL
+#define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL
+
+#define VPA_MIN_SIZE           640
+#define VPA_SIZE_OFFSET        0x4
+#define VPA_SHARED_PROC_OFFSET 0x9
+#define VPA_SHARED_PROC_VAL    0x2
+
+static target_ulong register_vpa(CPUState *env, target_ulong vpa)
+{
+    uint16_t size;
+    uint8_t tmp;
+
+    if (vpa == 0) {
+        hcall_dprintf("Can't cope with registering a VPA at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    if (vpa % env->dcache_line_size) {
+        return H_PARAMETER;
+    }
+    /* FIXME: bounds check the address */
+
+    size = lduw_phys(vpa + 0x4);
+
+    if (size < VPA_MIN_SIZE) {
+        return H_PARAMETER;
+    }
+
+    /* VPA is not allowed to cross a page boundary */
+    if ((vpa / 4096) != ((vpa + size - 1) / 4096)) {
+        return H_PARAMETER;
+    }
+
+    env->vpa = vpa;
+
+    tmp = ldub_phys(env->vpa + VPA_SHARED_PROC_OFFSET);
+    tmp |= VPA_SHARED_PROC_VAL;
+    stb_phys(env->vpa + VPA_SHARED_PROC_OFFSET, tmp);
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_vpa(CPUState *env, target_ulong vpa)
+{
+    if (env->slb_shadow) {
+        return H_RESOURCE;
+    }
+
+    if (env->dispatch_trace_log) {
+        return H_RESOURCE;
+    }
+
+    env->vpa = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_slb_shadow(CPUState *env, target_ulong addr)
+{
+    uint32_t size;
+
+    if (addr == 0) {
+        hcall_dprintf("Can't cope with SLB shadow at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    size = ldl_phys(addr + 0x4);
+    if (size < 0x8) {
+        return H_PARAMETER;
+    }
+
+    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa) {
+        return H_RESOURCE;
+    }
+
+    env->slb_shadow = addr;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_slb_shadow(CPUState *env, target_ulong addr)
+{
+    env->slb_shadow = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_dtl(CPUState *env, target_ulong addr)
+{
+    uint32_t size;
+
+    if (addr == 0) {
+        hcall_dprintf("Can't cope with DTL at logical 0\n");
+        return H_HARDWARE;
+    }
+
+    size = ldl_phys(addr + 0x4);
+
+    if (size < 48) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa) {
+        return H_RESOURCE;
+    }
+
+    env->dispatch_trace_log = addr;
+    env->dtl_size = size;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_dtl(CPUState *emv, target_ulong addr)
+{
+    env->dispatch_trace_log = 0;
+    env->dtl_size = 0;
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_register_vpa(CPUState *env, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong procno = args[1];
+    target_ulong vpa = args[2];
+    target_ulong ret = H_PARAMETER;
+    CPUState *tenv;
+
+    for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) {
+        if (tenv->cpu_index == procno) {
+            break;
+        }
+    }
+
+    if (!tenv) {
+        return H_PARAMETER;
+    }
+
+    switch (flags) {
+    case FLAGS_REGISTER_VPA:
+        ret = register_vpa(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_VPA:
+        ret = deregister_vpa(tenv, vpa);
+        break;
+
+    case FLAGS_REGISTER_SLBSHADOW:
+        ret = register_slb_shadow(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_SLBSHADOW:
+        ret = deregister_slb_shadow(tenv, vpa);
+        break;
+
+    case FLAGS_REGISTER_DTL:
+        ret = register_dtl(tenv, vpa);
+        break;
+
+    case FLAGS_DEREGISTER_DTL:
+        ret = deregister_dtl(tenv, vpa);
+        break;
+    }
+
+    return ret;
+}
+
+static target_ulong h_cede(CPUState *env, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    env->msr |= (1ULL << MSR_EE);
+    hreg_compute_hflags(env);
+    if (!cpu_has_work(env)) {
+        env->halted = 1;
+    }
+    return H_SUCCESS;
+}
+
 static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
@@ -327,6 +515,10 @@ static void hypercall_init(void)
     /* hcall-dabr */
     spapr_register_hypercall(H_SET_DABR, h_set_dabr);
 
+    /* hcall-splpar */
+    spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
+    spapr_register_hypercall(H_CEDE, h_cede);
+
     /* qemu/KVM-PPC specific hcalls */
     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 }
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index b4c2555..04b1259 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -721,6 +721,13 @@ struct CPUPPCState {
     uint32_t flags;
     uint64_t insns_flags;
 
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+    target_phys_addr_t vpa;
+    target_phys_addr_t slb_shadow;
+    target_phys_addr_t dispatch_trace_log;
+    uint32_t dtl_size;
+#endif /* TARGET_PPC64 */
+
     int error_code;
     uint32_t pending_interrupts;
 #if !defined(CONFIG_USER_ONLY)
commit 08942ac17922d923a7cc5cf9854e9cc4b150b942
Author: Ben Herrenschmidt <benh at kernel.crashing.org>
Date:   Fri Apr 1 15:15:32 2011 +1100

    Add a PAPR TCE-bypass mechanism for the pSeries machine
    
    Usually, PAPR virtual IO devices use a virtual IOMMU mechanism, TCEs,
    to mediate all DMA transfers.  While this is necessary for some sorts of
    operation, it can be complex to program and slow for others.
    
    This patch implements a mechanism for bypassing TCE translation, treating
    "IO" addresses as plain (guest) physical memory addresses.  This has two
    main uses:
     * Simple, but 64-bit aware programs like firmwares can use the VIO devices
    without the complexity of TCE setup.
     * The guest OS can optionally use the TCE bypass to improve performance in
    suitable situations.
    
    The mechanism used is a per-device flag which disables TCE translation.
    The flag is toggled with some (hypervisor-implemented) RTAS methods.
    
    Signed-off-by: Ben Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 8f14fcc..481a804 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -226,6 +226,12 @@ int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr, const void *buf,
             (unsigned long long)taddr, size);
 #endif
 
+    /* Check for bypass */
+    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
+        cpu_physical_memory_write(taddr, buf, size);
+        return 0;
+    }
+
     while (size) {
         uint64_t tce;
         uint32_t lsize;
@@ -313,6 +319,12 @@ int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr, void *buf,
             (unsigned long long)taddr, size);
 #endif
 
+    /* Check for bypass */
+    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
+        cpu_physical_memory_read(taddr, buf, size);
+        return 0;
+    }
+
     while (size) {
         uint64_t tce;
         uint32_t lsize;
@@ -513,6 +525,72 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
     return 0;
 }
 
+/* "quiesce" handling */
+
+static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
+{
+    dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
+
+    if (dev->rtce_table) {
+        size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
+            * sizeof(VIOsPAPR_RTCE);
+        memset(dev->rtce_table, 0, size);
+    }
+
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+}
+
+static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
+                                uint32_t nargs, target_ulong args,
+                                uint32_t nret, target_ulong rets)
+{
+    VIOsPAPRBus *bus = spapr->vio_bus;
+    VIOsPAPRDevice *dev;
+    uint32_t unit, enable;
+
+    if (nargs != 2) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    unit = rtas_ld(args, 0);
+    enable = rtas_ld(args, 1);
+    dev = spapr_vio_find_by_reg(bus, unit);
+    if (!dev) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    if (enable) {
+        dev->flags |= VIO_PAPR_FLAG_DMA_BYPASS;
+    } else {
+        dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
+    }
+
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+    VIOsPAPRBus *bus = spapr->vio_bus;
+    DeviceState *qdev;
+    VIOsPAPRDevice *dev = NULL;
+
+    if (nargs != 0) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)qdev;
+        spapr_vio_quiesce_one(dev);
+    }
+
+    rtas_st(rets, 0, 0);
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 {
     VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
@@ -591,6 +669,10 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
     spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
 
+    /* RTAS calls */
+    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
+    spapr_rtas_register("quiesce", rtas_quiesce);
+
     for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
         VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index b7d0daa..841b043 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -48,6 +48,8 @@ typedef struct VIOsPAPR_CRQ {
 typedef struct VIOsPAPRDevice {
     DeviceState qdev;
     uint32_t reg;
+    uint32_t flags;
+#define VIO_PAPR_FLAG_DMA_BYPASS        0x1
     qemu_irq qirq;
     uint32_t vio_irq_num;
     target_ulong signal_state;
@@ -104,4 +106,7 @@ void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
 void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
                         qemu_irq qirq, uint32_t vio_irq_num);
 
+int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
+void spapr_vio_quiesce(void);
+
 #endif /* _HW_SPAPR_VIO_H */
commit 6e270446d0e107b5227d8c51d2f85546f8811e99
Author: Ben Herrenschmidt <benh at kernel.crashing.org>
Date:   Fri Apr 1 15:15:31 2011 +1100

    Implement PAPR virtual SCSI interface (ibmvscsi)
    
    This patch implements the infrastructure and hypercalls necessary for
    the PAPR specified Virtual SCSI interface.  This is the normal method
    for providing (virtual) disks to PAPR partitions.
    
    Signed-off-by: Ben Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index cd7bb41..565e1fb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -234,7 +234,7 @@ obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
 obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-y += xics.o spapr_vty.o spapr_llan.o
+obj-ppc-y += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
 endif
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
diff --git a/hw/ppc-viosrp.h b/hw/ppc-viosrp.h
new file mode 100644
index 0000000..d8e365d
--- /dev/null
+++ b/hw/ppc-viosrp.h
@@ -0,0 +1,216 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for IBM RPA (RS/6000        */
+/* platform architecture) implementation of the SRP (SCSI RDMA Protocol)     */
+/* standard.  SRP is used on IBM iSeries and pSeries platforms to send SCSI  */
+/* commands between logical partitions.                                      */
+/*                                                                           */
+/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ)  */
+/* between partitions.  The definitions in this file are architected,        */
+/* and cannot be changed without breaking compatibility with other versions  */
+/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
+/* between logical partitions                                                */
+/*****************************************************************************/
+#ifndef PPC_VIOSRP_H
+#define PPC_VIOSRP_H
+
+#define SRP_VERSION "16.a"
+#define SRP_MAX_IU_LEN    256
+#define SRP_MAX_LOC_LEN 32
+
+union srp_iu {
+    struct srp_login_req login_req;
+    struct srp_login_rsp login_rsp;
+    struct srp_login_rej login_rej;
+    struct srp_i_logout i_logout;
+    struct srp_t_logout t_logout;
+    struct srp_tsk_mgmt tsk_mgmt;
+    struct srp_cmd cmd;
+    struct srp_rsp rsp;
+    uint8_t reserved[SRP_MAX_IU_LEN];
+};
+
+enum viosrp_crq_formats {
+    VIOSRP_SRP_FORMAT = 0x01,
+    VIOSRP_MAD_FORMAT = 0x02,
+    VIOSRP_OS400_FORMAT = 0x03,
+    VIOSRP_AIX_FORMAT = 0x04,
+    VIOSRP_LINUX_FORMAT = 0x06,
+    VIOSRP_INLINE_FORMAT = 0x07
+};
+
+enum viosrp_crq_status {
+    VIOSRP_OK = 0x0,
+    VIOSRP_NONRECOVERABLE_ERR = 0x1,
+    VIOSRP_VIOLATES_MAX_XFER = 0x2,
+    VIOSRP_PARTNER_PANIC = 0x3,
+    VIOSRP_DEVICE_BUSY = 0x8,
+    VIOSRP_ADAPTER_FAIL = 0x10,
+    VIOSRP_OK2 = 0x99,
+};
+
+struct viosrp_crq {
+    uint8_t valid;        /* used by RPA */
+    uint8_t format;        /* SCSI vs out-of-band */
+    uint8_t reserved;
+    uint8_t status;        /* non-scsi failure? (e.g. DMA failure) */
+    uint16_t timeout;        /* in seconds */
+    uint16_t IU_length;        /* in bytes */
+    uint64_t IU_data_ptr;    /* the TCE for transferring data */
+};
+
+/* MADs are Management requests above and beyond the IUs defined in the SRP
+ * standard.
+ */
+enum viosrp_mad_types {
+    VIOSRP_EMPTY_IU_TYPE = 0x01,
+    VIOSRP_ERROR_LOG_TYPE = 0x02,
+    VIOSRP_ADAPTER_INFO_TYPE = 0x03,
+    VIOSRP_HOST_CONFIG_TYPE = 0x04,
+    VIOSRP_CAPABILITIES_TYPE = 0x05,
+    VIOSRP_ENABLE_FAST_FAIL = 0x08,
+};
+
+enum viosrp_mad_status {
+    VIOSRP_MAD_SUCCESS = 0x00,
+    VIOSRP_MAD_NOT_SUPPORTED = 0xF1,
+    VIOSRP_MAD_FAILED = 0xF7,
+};
+
+enum viosrp_capability_type {
+    MIGRATION_CAPABILITIES = 0x01,
+    RESERVATION_CAPABILITIES = 0x02,
+};
+
+enum viosrp_capability_support {
+    SERVER_DOES_NOT_SUPPORTS_CAP = 0x0,
+    SERVER_SUPPORTS_CAP = 0x01,
+    SERVER_CAP_DATA = 0x02,
+};
+
+enum viosrp_reserve_type {
+    CLIENT_RESERVE_SCSI_2 = 0x01,
+};
+
+enum viosrp_capability_flag {
+    CLIENT_MIGRATED = 0x01,
+    CLIENT_RECONNECT = 0x02,
+    CAP_LIST_SUPPORTED = 0x04,
+    CAP_LIST_DATA = 0x08,
+};
+
+/*
+ * Common MAD header
+ */
+struct mad_common {
+    uint32_t type;
+    uint16_t status;
+    uint16_t length;
+    uint64_t tag;
+};
+
+/*
+ * All SRP (and MAD) requests normally flow from the
+ * client to the server.  There is no way for the server to send
+ * an asynchronous message back to the client.  The Empty IU is used
+ * to hang out a meaningless request to the server so that it can respond
+ * asynchrouously with something like a SCSI AER
+ */
+struct viosrp_empty_iu {
+    struct mad_common common;
+    uint64_t buffer;
+    uint32_t port;
+};
+
+struct viosrp_error_log {
+    struct mad_common common;
+    uint64_t buffer;
+};
+
+struct viosrp_adapter_info {
+    struct mad_common common;
+    uint64_t buffer;
+};
+
+struct viosrp_host_config {
+    struct mad_common common;
+    uint64_t buffer;
+};
+
+struct viosrp_fast_fail {
+    struct mad_common common;
+};
+
+struct viosrp_capabilities {
+    struct mad_common common;
+    uint64_t buffer;
+};
+
+struct mad_capability_common {
+    uint32_t cap_type;
+    uint16_t length;
+    uint16_t server_support;
+};
+
+struct mad_reserve_cap {
+    struct mad_capability_common common;
+    uint32_t type;
+};
+
+struct mad_migration_cap {
+    struct mad_capability_common common;
+    uint32_t ecl;
+};
+
+struct capabilities {
+    uint32_t flags;
+    char name[SRP_MAX_LOC_LEN];
+    char loc[SRP_MAX_LOC_LEN];
+    struct mad_migration_cap migration;
+    struct mad_reserve_cap reserve;
+};
+
+union mad_iu {
+    struct viosrp_empty_iu empty_iu;
+    struct viosrp_error_log error_log;
+    struct viosrp_adapter_info adapter_info;
+    struct viosrp_host_config host_config;
+    struct viosrp_fast_fail fast_fail;
+    struct viosrp_capabilities capabilities;
+};
+
+union viosrp_iu {
+    union srp_iu srp;
+    union mad_iu mad;
+};
+
+struct mad_adapter_info_data {
+    char srp_version[8];
+    char partition_name[96];
+    uint32_t partition_number;
+    uint32_t mad_version;
+    uint32_t os_type;
+    uint32_t port_max_txu[8];    /* per-port maximum transfer */
+};
+
+#endif
diff --git a/hw/spapr.c b/hw/spapr.c
index b432a9d..3bffaab 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -28,6 +28,7 @@
 #include "hw.h"
 #include "elf.h"
 #include "net.h"
+#include "blockdev.h"
 
 #include "hw/boards.h"
 #include "hw/ppc.h"
@@ -353,6 +354,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         }
     }
 
+    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
+        spapr_vscsi_create(spapr->vio_bus, 0x2000 + i,
+                           xics_find_qirq(spapr->icp, irq), irq);
+        irq++;
+    }
+
     if (kernel_filename) {
         uint64_t lowaddr = 0;
 
@@ -411,6 +418,7 @@ static QEMUMachine spapr_machine = {
     .max_cpus = MAX_CPUS,
     .no_vga = 1,
     .no_parallel = 1,
+    .use_scsi = 1,
 };
 
 static void spapr_machine_init(void)
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index ba16795..b7d0daa 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -101,4 +101,7 @@ void spapr_vty_create(VIOsPAPRBus *bus,
 void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
                        qemu_irq qirq, uint32_t vio_irq_num);
 
+void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
+                        qemu_irq qirq, uint32_t vio_irq_num);
+
 #endif /* _HW_SPAPR_VIO_H */
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
new file mode 100644
index 0000000..e142dae
--- /dev/null
+++ b/hw/spapr_vscsi.c
@@ -0,0 +1,988 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtual SCSI, aka ibmvscsi
+ *
+ * Copyright (c) 2010,2011 Benjamin Herrenschmidt, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * TODO:
+ *
+ *  - Cleanups :-)
+ *  - Sort out better how to assign devices to VSCSI instances
+ *  - Fix residual counts
+ *  - Add indirect descriptors support
+ *  - Maybe do autosense (PAPR seems to mandate it, linux doesn't care)
+ */
+#include "hw.h"
+#include "scsi.h"
+#include "scsi-defs.h"
+#include "net.h" /* Remove that when we can */
+#include "srp.h"
+#include "hw/qdev.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+#include "hw/ppc-viosrp.h"
+
+#include <libfdt.h>
+
+/*#define DEBUG_VSCSI*/
+
+#ifdef DEBUG_VSCSI
+#define dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+/*
+ * Virtual SCSI device
+ */
+
+/* Random numbers */
+#define VSCSI_MAX_SECTORS       4096
+#define VSCSI_REQ_LIMIT         24
+
+#define SCSI_SENSE_BUF_SIZE     96
+#define SRP_RSP_SENSE_DATA_LEN  18
+
+typedef union vscsi_crq {
+    struct viosrp_crq s;
+    uint8_t raw[16];
+} vscsi_crq;
+
+typedef struct vscsi_req {
+    vscsi_crq               crq;
+    union viosrp_iu         iu;
+
+    /* SCSI request tracking */
+    SCSIDevice              *sdev;
+    uint32_t                qtag; /* qemu tag != srp tag */
+    int                     lun;
+    int                     active;
+    long                    data_len;
+    int                     writing;
+    int                     sensing;
+    int                     senselen;
+    uint8_t                 sense[SCSI_SENSE_BUF_SIZE];
+
+    /* RDMA related bits */
+    uint8_t                 dma_fmt;
+    struct srp_direct_buf   ext_desc;
+    struct srp_direct_buf   *cur_desc;
+    struct srp_indirect_buf *ind_desc;
+    int                     local_desc;
+    int                     total_desc;
+} vscsi_req;
+
+
+typedef struct {
+    VIOsPAPRDevice vdev;
+    SCSIBus bus;
+    vscsi_req reqs[VSCSI_REQ_LIMIT];
+} VSCSIState;
+
+/* XXX Debug only */
+static VSCSIState *dbg_vscsi_state;
+
+
+static struct vscsi_req *vscsi_get_req(VSCSIState *s)
+{
+    vscsi_req *req;
+    int i;
+
+    for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
+        req = &s->reqs[i];
+        if (!req->active) {
+            memset(req, 0, sizeof(*req));
+            req->qtag = i;
+            req->active = 1;
+            return req;
+        }
+    }
+    return NULL;
+}
+
+static void vscsi_put_req(VSCSIState *s, vscsi_req *req)
+{
+    req->active = 0;
+}
+
+static vscsi_req *vscsi_find_req(VSCSIState *s, uint32_t tag)
+{
+    if (tag >= VSCSI_REQ_LIMIT || !s->reqs[tag].active) {
+        return NULL;
+    }
+    return &s->reqs[tag];
+}
+
+static void vscsi_decode_id_lun(uint64_t srp_lun, int *id, int *lun)
+{
+    /* XXX Figure that one out properly ! This is crackpot */
+    *id = (srp_lun >> 56) & 0x7f;
+    *lun = (srp_lun >> 48) & 0xff;
+}
+
+static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
+                         uint64_t length, uint8_t format)
+{
+    long rc, rc1;
+
+    /* First copy the SRP */
+    rc = spapr_tce_dma_write(&s->vdev, req->crq.s.IU_data_ptr,
+                             &req->iu, length);
+    if (rc) {
+        fprintf(stderr, "vscsi_send_iu: DMA write failure !\n");
+    }
+
+    req->crq.s.valid = 0x80;
+    req->crq.s.format = format;
+    req->crq.s.reserved = 0x00;
+    req->crq.s.timeout = cpu_to_be16(0x0000);
+    req->crq.s.IU_length = cpu_to_be16(length);
+    req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
+
+    if (rc == 0) {
+        req->crq.s.status = 0x99; /* Just needs to be non-zero */
+    } else {
+        req->crq.s.status = 0x00;
+    }
+
+    rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw);
+    if (rc1) {
+        fprintf(stderr, "vscsi_send_iu: Error sending response\n");
+        return rc1;
+    }
+
+    return rc;
+}
+
+static void vscsi_makeup_sense(VSCSIState *s, vscsi_req *req,
+                               uint8_t key, uint8_t asc, uint8_t ascq)
+{
+    req->senselen = SRP_RSP_SENSE_DATA_LEN;
+
+    /* Valid bit and 'current errors' */
+    req->sense[0] = (0x1 << 7 | 0x70);
+    /* Sense key */
+    req->sense[2] = key;
+    /* Additional sense length */
+    req->sense[7] = 0xa; /* 10 bytes */
+    /* Additional sense code */
+    req->sense[12] = asc;
+    req->sense[13] = ascq;
+}
+
+static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
+                          uint8_t status, int32_t res_in, int32_t res_out)
+{
+    union viosrp_iu *iu = &req->iu;
+    uint64_t tag = iu->srp.rsp.tag;
+    int total_len = sizeof(iu->srp.rsp);
+
+    dprintf("VSCSI: Sending resp status: 0x%x, "
+            "res_in: %d, res_out: %d\n", status, res_in, res_out);
+
+    memset(iu, 0, sizeof(struct srp_rsp));
+    iu->srp.rsp.opcode = SRP_RSP;
+    iu->srp.rsp.req_lim_delta = cpu_to_be32(1);
+    iu->srp.rsp.tag = tag;
+
+    /* Handle residuals */
+    if (res_in < 0) {
+        iu->srp.rsp.flags |= SRP_RSP_FLAG_DIUNDER;
+        res_in = -res_in;
+    } else if (res_in) {
+        iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER;
+    }
+    if (res_out < 0) {
+        iu->srp.rsp.flags |= SRP_RSP_FLAG_DOUNDER;
+        res_out = -res_out;
+    } else if (res_out) {
+        iu->srp.rsp.flags |= SRP_RSP_FLAG_DOOVER;
+    }
+    iu->srp.rsp.data_in_res_cnt = cpu_to_be32(res_in);
+    iu->srp.rsp.data_out_res_cnt = cpu_to_be32(res_out);
+
+    /* We don't do response data */
+    /* iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID; */
+    iu->srp.rsp.resp_data_len = cpu_to_be32(0);
+
+    /* Handle success vs. failure */
+    iu->srp.rsp.status = status;
+    if (status) {
+        iu->srp.rsp.sol_not = (iu->srp.cmd.sol_not & 0x04) >> 2;
+        if (req->senselen) {
+            req->iu.srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
+            req->iu.srp.rsp.sense_data_len = cpu_to_be32(req->senselen);
+            memcpy(req->iu.srp.rsp.data, req->sense, req->senselen);
+            total_len += req->senselen;
+        }
+    } else {
+        iu->srp.rsp.sol_not = (iu->srp.cmd.sol_not & 0x02) >> 1;
+    }
+
+    vscsi_send_iu(s, req, total_len, VIOSRP_SRP_FORMAT);
+    return 0;
+}
+
+static inline void vscsi_swap_desc(struct srp_direct_buf *desc)
+{
+    desc->va = be64_to_cpu(desc->va);
+    desc->len = be32_to_cpu(desc->len);
+}
+
+static int vscsi_srp_direct_data(VSCSIState *s, vscsi_req *req,
+                                 uint8_t *buf, uint32_t len)
+{
+    struct srp_direct_buf *md = req->cur_desc;
+    uint32_t llen;
+    int rc;
+
+    dprintf("VSCSI: direct segment 0x%x bytes, va=0x%llx desc len=0x%x\n",
+            len, (unsigned long long)md->va, md->len);
+
+    llen = MIN(len, md->len);
+    if (llen) {
+        if (req->writing) { /* writing = to device = reading from memory */
+            rc = spapr_tce_dma_read(&s->vdev, md->va, buf, llen);
+        } else {
+            rc = spapr_tce_dma_write(&s->vdev, md->va, buf, llen);
+        }
+    }
+    md->len -= llen;
+    md->va += llen;
+
+    if (rc) {
+        return -1;
+    }
+    return llen;
+}
+
+static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
+                                   uint8_t *buf, uint32_t len)
+{
+    struct srp_direct_buf *td = &req->ind_desc->table_desc;
+    struct srp_direct_buf *md = req->cur_desc;
+    int rc = 0;
+    uint32_t llen, total = 0;
+
+    dprintf("VSCSI: indirect segment 0x%x bytes, td va=0x%llx len=0x%x\n",
+            len, (unsigned long long)td->va, td->len);
+
+    /* While we have data ... */
+    while (len) {
+        /* If we have a descriptor but it's empty, go fetch a new one */
+        if (md && md->len == 0) {
+            /* More local available, use one */
+            if (req->local_desc) {
+                md = ++req->cur_desc;
+                --req->local_desc;
+                --req->total_desc;
+                td->va += sizeof(struct srp_direct_buf);
+            } else {
+                md = req->cur_desc = NULL;
+            }
+        }
+        /* No descriptor at hand, fetch one */
+        if (!md) {
+            if (!req->total_desc) {
+                dprintf("VSCSI:   Out of descriptors !\n");
+                break;
+            }
+            md = req->cur_desc = &req->ext_desc;
+            dprintf("VSCSI:   Reading desc from 0x%llx\n",
+                    (unsigned long long)td->va);
+            rc = spapr_tce_dma_read(&s->vdev, td->va, md,
+                                    sizeof(struct srp_direct_buf));
+            if (rc) {
+                dprintf("VSCSI: tce_dma_read -> %d reading ext_desc\n", rc);
+                break;
+            }
+            vscsi_swap_desc(md);
+            td->va += sizeof(struct srp_direct_buf);
+            --req->total_desc;
+        }
+        dprintf("VSCSI:   [desc va=0x%llx,len=0x%x] remaining=0x%x\n",
+                (unsigned long long)md->va, md->len, len);
+
+        /* Perform transfer */
+        llen = MIN(len, md->len);
+        if (req->writing) { /* writing = to device = reading from memory */
+            rc = spapr_tce_dma_read(&s->vdev, md->va, buf, llen);
+        } else {
+            rc = spapr_tce_dma_write(&s->vdev, md->va, buf, llen);
+        }
+        if (rc) {
+            dprintf("VSCSI: tce_dma_r/w(%d) -> %d\n", req->writing, rc);
+            break;
+        }
+        dprintf("VSCSI:     data: %02x %02x %02x %02x...\n",
+                buf[0], buf[1], buf[2], buf[3]);
+
+        len -= llen;
+        buf += llen;
+        total += llen;
+        md->va += llen;
+        md->len -= llen;
+    }
+    return rc ? -1 : total;
+}
+
+static int vscsi_srp_transfer_data(VSCSIState *s, vscsi_req *req,
+                                   int writing, uint8_t *buf, uint32_t len)
+{
+    int err = 0;
+
+    switch (req->dma_fmt) {
+    case SRP_NO_DATA_DESC:
+        dprintf("VSCSI: no data desc transfer, skipping 0x%x bytes\n", len);
+        break;
+    case SRP_DATA_DESC_DIRECT:
+        err = vscsi_srp_direct_data(s, req, buf, len);
+        break;
+    case SRP_DATA_DESC_INDIRECT:
+        err = vscsi_srp_indirect_data(s, req, buf, len);
+        break;
+    }
+    return err;
+}
+
+/* Bits from linux srp */
+static int data_out_desc_size(struct srp_cmd *cmd)
+{
+    int size = 0;
+    uint8_t fmt = cmd->buf_fmt >> 4;
+
+    switch (fmt) {
+    case SRP_NO_DATA_DESC:
+        break;
+    case SRP_DATA_DESC_DIRECT:
+        size = sizeof(struct srp_direct_buf);
+        break;
+    case SRP_DATA_DESC_INDIRECT:
+        size = sizeof(struct srp_indirect_buf) +
+            sizeof(struct srp_direct_buf)*cmd->data_out_desc_cnt;
+        break;
+    default:
+        break;
+    }
+    return size;
+}
+
+static int vscsi_preprocess_desc(vscsi_req *req)
+{
+    struct srp_cmd *cmd = &req->iu.srp.cmd;
+    int offset, i;
+
+    offset = cmd->add_cdb_len & ~3;
+
+    if (req->writing) {
+        req->dma_fmt = cmd->buf_fmt >> 4;
+    } else {
+        offset += data_out_desc_size(cmd);
+        req->dma_fmt = cmd->buf_fmt & ((1U << 4) - 1);
+    }
+
+    switch (req->dma_fmt) {
+    case SRP_NO_DATA_DESC:
+        break;
+    case SRP_DATA_DESC_DIRECT:
+        req->cur_desc = (struct srp_direct_buf *)(cmd->add_data + offset);
+        req->total_desc = req->local_desc = 1;
+        vscsi_swap_desc(req->cur_desc);
+        dprintf("VSCSI: using direct RDMA %s, 0x%x bytes MD: 0x%llx\n",
+                req->writing ? "write" : "read",
+                req->cur_desc->len, (unsigned long long)req->cur_desc->va);
+        break;
+    case SRP_DATA_DESC_INDIRECT:
+        req->ind_desc = (struct srp_indirect_buf *)(cmd->add_data + offset);
+        vscsi_swap_desc(&req->ind_desc->table_desc);
+        req->total_desc = req->ind_desc->table_desc.len /
+            sizeof(struct srp_direct_buf);
+        req->local_desc = req->writing ? cmd->data_out_desc_cnt :
+            cmd->data_in_desc_cnt;
+        for (i = 0; i < req->local_desc; i++) {
+            vscsi_swap_desc(&req->ind_desc->desc_list[i]);
+        }
+        req->cur_desc = req->local_desc ? &req->ind_desc->desc_list[0] : NULL;
+        dprintf("VSCSI: using indirect RDMA %s, 0x%x bytes %d descs "
+                "(%d local) VA: 0x%llx\n",
+                req->writing ? "read" : "write",
+                be32_to_cpu(req->ind_desc->len),
+                req->total_desc, req->local_desc,
+                (unsigned long long)req->ind_desc->table_desc.va);
+        break;
+    default:
+        fprintf(stderr,
+                "vscsi_preprocess_desc: Unknown format %x\n", req->dma_fmt);
+        return -1;
+    }
+
+    return 0;
+}
+
+static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
+{
+    SCSIDevice *sdev = req->sdev;
+    uint8_t *cdb = req->iu.srp.cmd.cdb;
+    int n;
+
+    cdb[0] = 3;
+    cdb[1] = 0;
+    cdb[2] = 0;
+    cdb[3] = 0;
+    cdb[4] = 96;
+    cdb[5] = 0;
+    req->sensing = 1;
+    n = sdev->info->send_command(sdev, req->qtag, cdb, req->lun);
+    dprintf("VSCSI: Queued request sense tag 0x%x\n", req->qtag);
+    if (n < 0) {
+        fprintf(stderr, "VSCSI: REQUEST_SENSE wants write data !?!?!?\n");
+        sdev->info->cancel_io(sdev, req->qtag);
+        vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
+        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+        vscsi_put_req(s, req);
+        return;
+    } else if (n == 0) {
+        return;
+    }
+    sdev->info->read_data(sdev, req->qtag);
+}
+
+/* Callback to indicate that the SCSI layer has completed a transfer.  */
+static void vscsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
+                                   uint32_t arg)
+{
+    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, bus->qbus.parent);
+    vscsi_req *req = vscsi_find_req(s, tag);
+    SCSIDevice *sdev;
+    uint8_t *buf;
+    int32_t res_in = 0, res_out = 0;
+    int len, rc = 0;
+
+    dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
+            reason, tag, arg, req);
+    if (req == NULL) {
+        fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", tag);
+        return;
+    }
+    sdev = req->sdev;
+
+    if (req->sensing) {
+        if (reason == SCSI_REASON_DONE) {
+            dprintf("VSCSI: Sense done !\n");
+            vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+            vscsi_put_req(s, req);
+        } else {
+            uint8_t *buf = sdev->info->get_buf(sdev, tag);
+
+            len = MIN(arg, SCSI_SENSE_BUF_SIZE);
+            dprintf("VSCSI: Sense data, %d bytes:\n", len);
+            dprintf("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
+                    buf[0], buf[1], buf[2], buf[3],
+                    buf[4], buf[5], buf[6], buf[7]);
+            dprintf("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
+                    buf[8], buf[9], buf[10], buf[11],
+                    buf[12], buf[13], buf[14], buf[15]);
+            memcpy(req->sense, buf, len);
+            req->senselen = len;
+            sdev->info->read_data(sdev, req->qtag);
+        }
+        return;
+    }
+
+    if (reason == SCSI_REASON_DONE) {
+        dprintf("VSCSI: Command complete err=%d\n", arg);
+        if (arg == 0) {
+            /* We handle overflows, not underflows for normal commands,
+             * but hopefully nobody cares
+             */
+            if (req->writing) {
+                res_out = req->data_len;
+            } else {
+                res_in = req->data_len;
+            }
+            vscsi_send_rsp(s, req, 0, res_in, res_out);
+        } else if (arg == CHECK_CONDITION) {
+            dprintf("VSCSI: Got CHECK_CONDITION, requesting sense...\n");
+            vscsi_send_request_sense(s, req);
+            return;
+        } else {
+            vscsi_send_rsp(s, req, arg, 0, 0);
+        }
+        vscsi_put_req(s, req);
+        return;
+    }
+
+    /* "arg" is how much we have read for reads and how much we want
+     * to write for writes (ie, how much is to be DMA'd)
+     */
+    if (arg) {
+        buf = sdev->info->get_buf(sdev, tag);
+        rc = vscsi_srp_transfer_data(s, req, req->writing, buf, arg);
+    }
+    if (rc < 0) {
+        fprintf(stderr, "VSCSI: RDMA error rc=%d!\n", rc);
+        sdev->info->cancel_io(sdev, req->qtag);
+        vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
+        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+        vscsi_put_req(s, req);
+        return;
+    }
+
+    /* Start next chunk */
+    req->data_len -= rc;
+    if (req->writing) {
+        sdev->info->write_data(sdev, req->qtag);
+    } else {
+        sdev->info->read_data(sdev, req->qtag);
+    }
+}
+
+static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
+{
+    union viosrp_iu *iu = &req->iu;
+    struct srp_login_rsp *rsp = &iu->srp.login_rsp;
+    uint64_t tag = iu->srp.rsp.tag;
+
+    dprintf("VSCSI: Got login, sendin response !\n");
+
+    /* TODO handle case that requested size is wrong and
+     * buffer format is wrong
+     */
+    memset(iu, 0, sizeof(struct srp_login_rsp));
+    rsp->opcode = SRP_LOGIN_RSP;
+    /* Don't advertise quite as many request as we support to
+     * keep room for management stuff etc...
+     */
+    rsp->req_lim_delta = cpu_to_be32(VSCSI_REQ_LIMIT-2);
+    rsp->tag = tag;
+    rsp->max_it_iu_len = cpu_to_be32(sizeof(union srp_iu));
+    rsp->max_ti_iu_len = cpu_to_be32(sizeof(union srp_iu));
+    /* direct and indirect */
+    rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT);
+
+    vscsi_send_iu(s, req, sizeof(*rsp), VIOSRP_SRP_FORMAT);
+}
+
+static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req)
+{
+    uint8_t *cdb = req->iu.srp.cmd.cdb;
+    uint8_t resp_data[36];
+    int rc, len, alen;
+
+    /* We dont do EVPD. Also check that page_code is 0 */
+    if ((cdb[1] & 0x01) || (cdb[1] & 0x01) || cdb[2] != 0) {
+        /* Send INVALID FIELD IN CDB */
+        vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x24, 0);
+        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+        return;
+    }
+    alen = cdb[3];
+    alen = (alen << 8) | cdb[4];
+    len = MIN(alen, 36);
+
+    /* Fake up inquiry using PQ=3 */
+    memset(resp_data, 0, 36);
+    resp_data[0] = 0x7f;   /* Not capable of supporting a device here */
+    resp_data[2] = 0x06;   /* SPS-4 */
+    resp_data[3] = 0x02;   /* Resp data format */
+    resp_data[4] = 36 - 5; /* Additional length */
+    resp_data[7] = 0x10;   /* Sync transfers */
+    memcpy(&resp_data[16], "QEMU EMPTY      ", 16);
+    memcpy(&resp_data[8], "QEMU    ", 8);
+
+    req->writing = 0;
+    vscsi_preprocess_desc(req);
+    rc = vscsi_srp_transfer_data(s, req, 0, resp_data, len);
+    if (rc < 0) {
+        vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
+        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+    } else {
+        vscsi_send_rsp(s, req, 0, 36 - rc, 0);
+    }
+}
+
+static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
+{
+    union srp_iu *srp = &req->iu.srp;
+    SCSIDevice *sdev;
+    int n, id, lun;
+
+    vscsi_decode_id_lun(be64_to_cpu(srp->cmd.lun), &id, &lun);
+
+    /* Qemu vs. linux issue with LUNs to be sorted out ... */
+    sdev = (id < 8 && lun < 16) ? s->bus.devs[id] : NULL;
+    if (!sdev) {
+        dprintf("VSCSI: Command for id %d with no drive\n", id);
+        if (srp->cmd.cdb[0] == INQUIRY) {
+            vscsi_inquiry_no_target(s, req);
+        } else {
+            vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x24, 0x00);
+            vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+        } return 1;
+    }
+
+    req->sdev = sdev;
+    req->lun = lun;
+    n = sdev->info->send_command(sdev, req->qtag, srp->cmd.cdb, lun);
+
+    dprintf("VSCSI: Queued command tag 0x%x CMD 0x%x ID %d LUN %d ret: %d\n",
+            req->qtag, srp->cmd.cdb[0], id, lun, n);
+
+    if (n) {
+        /* Transfer direction must be set before preprocessing the
+         * descriptors
+         */
+        req->writing = (n < 1);
+
+        /* Preprocess RDMA descriptors */
+        vscsi_preprocess_desc(req);
+    }
+
+    /* Get transfer direction and initiate transfer */
+    if (n > 0) {
+        req->data_len = n;
+        sdev->info->read_data(sdev, req->qtag);
+    } else if (n < 0) {
+        req->data_len = -n;
+        sdev->info->write_data(sdev, req->qtag);
+    }
+    /* Don't touch req here, it may have been recycled already */
+
+    return 0;
+}
+
+static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
+{
+    union viosrp_iu *iu = &req->iu;
+    int fn;
+
+    fprintf(stderr, "vscsi_process_tsk_mgmt %02x\n",
+            iu->srp.tsk_mgmt.tsk_mgmt_func);
+
+    switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
+#if 0 /* We really don't deal with these for now */
+    case SRP_TSK_ABORT_TASK:
+        fn = ABORT_TASK;
+        break;
+    case SRP_TSK_ABORT_TASK_SET:
+        fn = ABORT_TASK_SET;
+        break;
+    case SRP_TSK_CLEAR_TASK_SET:
+        fn = CLEAR_TASK_SET;
+        break;
+    case SRP_TSK_LUN_RESET:
+        fn = LOGICAL_UNIT_RESET;
+        break;
+    case SRP_TSK_CLEAR_ACA:
+        fn = CLEAR_ACA;
+        break;
+#endif
+    default:
+        fn = 0;
+    }
+    if (fn) {
+        /* XXX Send/Handle target task management */
+        ;
+    } else {
+        vscsi_makeup_sense(s, req, ILLEGAL_REQUEST, 0x20, 0);
+        vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
+    }
+    return !fn;
+}
+
+static int vscsi_handle_srp_req(VSCSIState *s, vscsi_req *req)
+{
+    union srp_iu *srp = &req->iu.srp;
+    int done = 1;
+    uint8_t opcode = srp->rsp.opcode;
+
+    switch (opcode) {
+    case SRP_LOGIN_REQ:
+        vscsi_process_login(s, req);
+        break;
+    case SRP_TSK_MGMT:
+        done = vscsi_process_tsk_mgmt(s, req);
+        break;
+    case SRP_CMD:
+        done = vscsi_queue_cmd(s, req);
+        break;
+    case SRP_LOGIN_RSP:
+    case SRP_I_LOGOUT:
+    case SRP_T_LOGOUT:
+    case SRP_RSP:
+    case SRP_CRED_REQ:
+    case SRP_CRED_RSP:
+    case SRP_AER_REQ:
+    case SRP_AER_RSP:
+        fprintf(stderr, "VSCSI: Unsupported opcode %02x\n", opcode);
+        break;
+    default:
+        fprintf(stderr, "VSCSI: Unknown type %02x\n", opcode);
+    }
+
+    return done;
+}
+
+static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req)
+{
+    struct viosrp_adapter_info *sinfo;
+    struct mad_adapter_info_data info;
+    int rc;
+
+    sinfo = &req->iu.mad.adapter_info;
+
+#if 0 /* What for ? */
+    rc = spapr_tce_dma_read(&s->vdev, be64_to_cpu(sinfo->buffer),
+                            &info, be16_to_cpu(sinfo->common.length));
+    if (rc) {
+        fprintf(stderr, "vscsi_send_adapter_info: DMA read failure !\n");
+    }
+#endif
+    memset(&info, 0, sizeof(info));
+    strcpy(info.srp_version, SRP_VERSION);
+    strncpy(info.partition_name, "qemu", sizeof("qemu"));
+    info.partition_number = cpu_to_be32(0);
+    info.mad_version = cpu_to_be32(1);
+    info.os_type = cpu_to_be32(2);
+    info.port_max_txu[0] = cpu_to_be32(VSCSI_MAX_SECTORS << 9);
+
+    rc = spapr_tce_dma_write(&s->vdev, be64_to_cpu(sinfo->buffer),
+                             &info, be16_to_cpu(sinfo->common.length));
+    if (rc)  {
+        fprintf(stderr, "vscsi_send_adapter_info: DMA write failure !\n");
+    }
+
+    sinfo->common.status = rc ? cpu_to_be32(1) : 0;
+
+    return vscsi_send_iu(s, req, sizeof(*sinfo), VIOSRP_MAD_FORMAT);
+}
+
+static int vscsi_handle_mad_req(VSCSIState *s, vscsi_req *req)
+{
+    union mad_iu *mad = &req->iu.mad;
+
+    switch (be32_to_cpu(mad->empty_iu.common.type)) {
+    case VIOSRP_EMPTY_IU_TYPE:
+        fprintf(stderr, "Unsupported EMPTY MAD IU\n");
+        break;
+    case VIOSRP_ERROR_LOG_TYPE:
+        fprintf(stderr, "Unsupported ERROR LOG MAD IU\n");
+        mad->error_log.common.status = cpu_to_be16(1);
+        vscsi_send_iu(s, req, sizeof(mad->error_log), VIOSRP_MAD_FORMAT);
+        break;
+    case VIOSRP_ADAPTER_INFO_TYPE:
+        vscsi_send_adapter_info(s, req);
+        break;
+    case VIOSRP_HOST_CONFIG_TYPE:
+        mad->host_config.common.status = cpu_to_be16(1);
+        vscsi_send_iu(s, req, sizeof(mad->host_config), VIOSRP_MAD_FORMAT);
+        break;
+    default:
+        fprintf(stderr, "VSCSI: Unknown MAD type %02x\n",
+                be32_to_cpu(mad->empty_iu.common.type));
+    }
+
+    return 1;
+}
+
+static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
+{
+    vscsi_req *req;
+    int done;
+
+    req = vscsi_get_req(s);
+    if (req == NULL) {
+        fprintf(stderr, "VSCSI: Failed to get a request !\n");
+        return;
+    }
+
+    /* We only support a limited number of descriptors, we know
+     * the ibmvscsi driver uses up to 10 max, so it should fit
+     * in our 256 bytes IUs. If not we'll have to increase the size
+     * of the structure.
+     */
+    if (crq->s.IU_length > sizeof(union viosrp_iu)) {
+        fprintf(stderr, "VSCSI: SRP IU too long (%d bytes) !\n",
+                crq->s.IU_length);
+        return;
+    }
+
+    /* XXX Handle failure differently ? */
+    if (spapr_tce_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu,
+                           crq->s.IU_length)) {
+        fprintf(stderr, "vscsi_got_payload: DMA read failure !\n");
+        qemu_free(req);
+    }
+    memcpy(&req->crq, crq, sizeof(vscsi_crq));
+
+    if (crq->s.format == VIOSRP_MAD_FORMAT) {
+        done = vscsi_handle_mad_req(s, req);
+    } else {
+        done = vscsi_handle_srp_req(s, req);
+    }
+
+    if (done) {
+        vscsi_put_req(s, req);
+    }
+}
+
+
+static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
+{
+    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+    vscsi_crq crq;
+
+    memcpy(crq.raw, crq_data, 16);
+    crq.s.timeout = be16_to_cpu(crq.s.timeout);
+    crq.s.IU_length = be16_to_cpu(crq.s.IU_length);
+    crq.s.IU_data_ptr = be64_to_cpu(crq.s.IU_data_ptr);
+
+    dprintf("VSCSI: do_crq %02x %02x ...\n", crq.raw[0], crq.raw[1]);
+
+    switch (crq.s.valid) {
+    case 0xc0: /* Init command/response */
+
+        /* Respond to initialization request */
+        if (crq.s.format == 0x01) {
+            memset(crq.raw, 0, 16);
+            crq.s.valid = 0xc0;
+            crq.s.format = 0x02;
+            spapr_vio_send_crq(dev, crq.raw);
+        }
+
+        /* Note that in hotplug cases, we might get a 0x02
+         * as a result of us emitting the init request
+         */
+
+        break;
+    case 0xff: /* Link event */
+
+        /* Not handled for now */
+
+        break;
+    case 0x80: /* Payloads */
+        switch (crq.s.format) {
+        case VIOSRP_SRP_FORMAT: /* AKA VSCSI request */
+        case VIOSRP_MAD_FORMAT: /* AKA VSCSI response */
+            vscsi_got_payload(s, &crq);
+            break;
+        case VIOSRP_OS400_FORMAT:
+        case VIOSRP_AIX_FORMAT:
+        case VIOSRP_LINUX_FORMAT:
+        case VIOSRP_INLINE_FORMAT:
+            fprintf(stderr, "vscsi_do_srq: Unsupported payload format %02x\n",
+                    crq.s.format);
+            break;
+        default:
+            fprintf(stderr, "vscsi_do_srq: Unknown payload format %02x\n",
+                    crq.s.format);
+        }
+        break;
+    default:
+        fprintf(stderr, "vscsi_do_crq: unknown CRQ %02x %02x ...\n",
+                crq.raw[0], crq.raw[1]);
+    };
+
+    return 0;
+}
+
+static int spapr_vscsi_init(VIOsPAPRDevice *dev)
+{
+    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+    int i;
+
+    dbg_vscsi_state = s;
+
+    /* Initialize qemu request tags */
+    memset(s->reqs, 0, sizeof(s->reqs));
+    for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
+        s->reqs[i].qtag = i;
+    }
+
+    dev->crq.SendFunc = vscsi_do_crq;
+
+    scsi_bus_new(&s->bus, &dev->qdev, 1, VSCSI_REQ_LIMIT,
+                 vscsi_command_complete);
+    if (!dev->qdev.hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus);
+    }
+
+    return 0;
+}
+
+void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
+                        qemu_irq qirq, uint32_t vio_irq_num)
+{
+    DeviceState *dev;
+    VIOsPAPRDevice *sdev;
+
+    dev = qdev_create(&bus->bus, "spapr-vscsi");
+    qdev_prop_set_uint32(dev, "reg", reg);
+
+    qdev_init_nofail(dev);
+
+    sdev = (VIOsPAPRDevice *)dev;
+    sdev->qirq = qirq;
+    sdev->vio_irq_num = vio_irq_num;
+}
+
+static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+{
+    int ret;
+
+    ret = fdt_setprop_cell(fdt, node_off, "#address-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "#size-cells", 0);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static VIOsPAPRDeviceInfo spapr_vscsi = {
+    .init = spapr_vscsi_init,
+    .devnode = spapr_vscsi_devnode,
+    .dt_name = "v-scsi",
+    .dt_type = "vscsi",
+    .dt_compatible = "IBM,v-scsi",
+    .signal_mask = 0x00000001,
+    .qdev.name = "spapr-vscsi",
+    .qdev.size = sizeof(VSCSIState),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0x2000),
+        DEFINE_PROP_UINT32("dma-window", VIOsPAPRDevice,
+                           rtce_window_size, 0x10000000),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void spapr_vscsi_register(void)
+{
+    spapr_vio_bus_register_withprop(&spapr_vscsi);
+}
+device_init(spapr_vscsi_register);
diff --git a/hw/srp.h b/hw/srp.h
new file mode 100644
index 0000000..afcd135
--- /dev/null
+++ b/hw/srp.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef SCSI_SRP_H
+#define SCSI_SRP_H
+
+/*
+ * Structures and constants for the SCSI RDMA Protocol (SRP) as
+ * defined by the INCITS T10 committee.  This file was written using
+ * draft Revision 16a of the SRP standard.
+ */
+
+enum {
+
+    SRP_LOGIN_REQ = 0x00,
+    SRP_TSK_MGMT  = 0x01,
+    SRP_CMD       = 0x02,
+    SRP_I_LOGOUT  = 0x03,
+    SRP_LOGIN_RSP = 0xc0,
+    SRP_RSP       = 0xc1,
+    SRP_LOGIN_REJ = 0xc2,
+    SRP_T_LOGOUT  = 0x80,
+    SRP_CRED_REQ  = 0x81,
+    SRP_AER_REQ   = 0x82,
+    SRP_CRED_RSP  = 0x41,
+    SRP_AER_RSP   = 0x42
+};
+
+enum {
+    SRP_BUF_FORMAT_DIRECT   = 1 << 1,
+    SRP_BUF_FORMAT_INDIRECT = 1 << 2
+};
+
+enum {
+    SRP_NO_DATA_DESC       = 0,
+    SRP_DATA_DESC_DIRECT   = 1,
+    SRP_DATA_DESC_INDIRECT = 2
+};
+
+enum {
+    SRP_TSK_ABORT_TASK     = 0x01,
+    SRP_TSK_ABORT_TASK_SET = 0x02,
+    SRP_TSK_CLEAR_TASK_SET = 0x04,
+    SRP_TSK_LUN_RESET      = 0x08,
+    SRP_TSK_CLEAR_ACA      = 0x40
+};
+
+enum srp_login_rej_reason {
+    SRP_LOGIN_REJ_UNABLE_ESTABLISH_CHANNEL   = 0x00010000,
+    SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES     = 0x00010001,
+    SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE = 0x00010002,
+    SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL   = 0x00010003,
+    SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT = 0x00010004,
+    SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED  = 0x00010005,
+    SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED      = 0x00010006
+};
+
+enum {
+    SRP_REV10_IB_IO_CLASS  = 0xff00,
+    SRP_REV16A_IB_IO_CLASS = 0x0100
+};
+
+struct srp_direct_buf {
+    uint64_t    va;
+    uint32_t    key;
+    uint32_t    len;
+};
+
+/*
+ * We need the packed attribute because the SRP spec puts the list of
+ * descriptors at an offset of 20, which is not aligned to the size of
+ * struct srp_direct_buf.  The whole structure must be packed to avoid
+ * having the 20-byte structure padded to 24 bytes on 64-bit architectures.
+ */
+struct srp_indirect_buf {
+    struct srp_direct_buf    table_desc;
+    uint32_t                 len;
+    struct srp_direct_buf    desc_list[0];
+} __attribute__((packed));
+
+enum {
+    SRP_MULTICHAN_SINGLE = 0,
+    SRP_MULTICHAN_MULTI  = 1
+};
+
+struct srp_login_req {
+    uint8_t    opcode;
+    uint8_t    reserved1[7];
+    uint64_t   tag;
+    uint32_t   req_it_iu_len;
+    uint8_t    reserved2[4];
+    uint16_t   req_buf_fmt;
+    uint8_t    req_flags;
+    uint8_t    reserved3[5];
+    uint8_t    initiator_port_id[16];
+    uint8_t    target_port_id[16];
+};
+
+/*
+ * The SRP spec defines the size of the LOGIN_RSP structure to be 52
+ * bytes, so it needs to be packed to avoid having it padded to 56
+ * bytes on 64-bit architectures.
+ */
+struct srp_login_rsp {
+    uint8_t    opcode;
+    uint8_t    reserved1[3];
+    uint32_t   req_lim_delta;
+    uint64_t   tag;
+    uint32_t   max_it_iu_len;
+    uint32_t   max_ti_iu_len;
+    uint16_t   buf_fmt;
+    uint8_t    rsp_flags;
+    uint8_t    reserved2[25];
+} __attribute__((packed));
+
+struct srp_login_rej {
+    uint8_t    opcode;
+    uint8_t    reserved1[3];
+    uint32_t   reason;
+    uint64_t   tag;
+    uint8_t    reserved2[8];
+    uint16_t   buf_fmt;
+    uint8_t    reserved3[6];
+};
+
+struct srp_i_logout {
+    uint8_t    opcode;
+    uint8_t    reserved[7];
+    uint64_t   tag;
+};
+
+struct srp_t_logout {
+    uint8_t    opcode;
+    uint8_t    sol_not;
+    uint8_t    reserved[2];
+    uint32_t   reason;
+    uint64_t   tag;
+};
+
+/*
+ * We need the packed attribute because the SRP spec only aligns the
+ * 8-byte LUN field to 4 bytes.
+ */
+struct srp_tsk_mgmt {
+    uint8_t    opcode;
+    uint8_t    sol_not;
+    uint8_t    reserved1[6];
+    uint64_t   tag;
+    uint8_t    reserved2[4];
+    uint64_t   lun __attribute__((packed));
+    uint8_t    reserved3[2];
+    uint8_t    tsk_mgmt_func;
+    uint8_t    reserved4;
+    uint64_t   task_tag;
+    uint8_t    reserved5[8];
+};
+
+/*
+ * We need the packed attribute because the SRP spec only aligns the
+ * 8-byte LUN field to 4 bytes.
+ */
+struct srp_cmd {
+    uint8_t    opcode;
+    uint8_t    sol_not;
+    uint8_t    reserved1[3];
+    uint8_t    buf_fmt;
+    uint8_t    data_out_desc_cnt;
+    uint8_t    data_in_desc_cnt;
+    uint64_t   tag;
+    uint8_t    reserved2[4];
+    uint64_t   lun __attribute__((packed));
+    uint8_t    reserved3;
+    uint8_t    task_attr;
+    uint8_t    reserved4;
+    uint8_t    add_cdb_len;
+    uint8_t    cdb[16];
+    uint8_t    add_data[0];
+};
+
+enum {
+    SRP_RSP_FLAG_RSPVALID = 1 << 0,
+    SRP_RSP_FLAG_SNSVALID = 1 << 1,
+    SRP_RSP_FLAG_DOOVER   = 1 << 2,
+    SRP_RSP_FLAG_DOUNDER  = 1 << 3,
+    SRP_RSP_FLAG_DIOVER   = 1 << 4,
+    SRP_RSP_FLAG_DIUNDER  = 1 << 5
+};
+
+/*
+ * The SRP spec defines the size of the RSP structure to be 36 bytes,
+ * so it needs to be packed to avoid having it padded to 40 bytes on
+ * 64-bit architectures.
+ */
+struct srp_rsp {
+    uint8_t    opcode;
+    uint8_t    sol_not;
+    uint8_t    reserved1[2];
+    uint32_t   req_lim_delta;
+    uint64_t   tag;
+    uint8_t    reserved2[2];
+    uint8_t    flags;
+    uint8_t    status;
+    uint32_t   data_out_res_cnt;
+    uint32_t   data_in_res_cnt;
+    uint32_t   sense_data_len;
+    uint32_t   resp_data_len;
+    uint8_t    data[0];
+} __attribute__((packed));
+
+#endif /* SCSI_SRP_H */
commit b45d63b62f0c05eb54bba0fafaf29b9b3f4dd99a
Author: Ben Herrenschmidt <benh at kernel.crashing.org>
Date:   Fri Apr 1 15:15:30 2011 +1100

    Implement PAPR CRQ hypercalls
    
    This patch implements the infrastructure and hypercalls necessary for the
    PAPR specified CRQ (Command Request Queue) mechanism.  This general
    request queueing system is used by many of the PAPR virtual IO devices,
    including the virtual scsi adapter.
    
    Signed-off-by: Ben Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index c7306d9..b432a9d 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -67,7 +67,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
     char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
-        "\0hcall-tce";
+        "\0hcall-tce\0hcall-vio";
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 39d77ee..8f14fcc 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -28,6 +28,7 @@
 #include "hw/sysbus.h"
 #include "kvm.h"
 #include "device_tree.h"
+#include "kvm_ppc.h"
 
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
@@ -359,6 +360,159 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr)
     return tswap64(val);
 }
 
+/*
+ * CRQ handling
+ */
+static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong queue_addr = args[1];
+    target_ulong queue_len = args[2];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("h_reg_crq on non-existent unit 0x"
+                      TARGET_FMT_lx "\n", reg);
+        return H_PARAMETER;
+    }
+
+    /* We can't grok a queue size bigger than 256M for now */
+    if (queue_len < 0x1000 || queue_len > 0x10000000) {
+        hcall_dprintf("h_reg_crq, queue size too small or too big (0x%llx)\n",
+                      (unsigned long long)queue_len);
+        return H_PARAMETER;
+    }
+
+    /* Check queue alignment */
+    if (queue_addr & 0xfff) {
+        hcall_dprintf("h_reg_crq, queue not aligned (0x%llx)\n",
+                      (unsigned long long)queue_addr);
+        return H_PARAMETER;
+    }
+
+    /* Check if device supports CRQs */
+    if (!dev->crq.SendFunc) {
+        return H_NOT_FOUND;
+    }
+
+
+    /* Already a queue ? */
+    if (dev->crq.qsize) {
+        return H_RESOURCE;
+    }
+    dev->crq.qladdr = queue_addr;
+    dev->crq.qsize = queue_len;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
+            TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
+            reg, queue_addr, queue_len);
+    return H_SUCCESS;
+}
+
+static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("h_free_crq on non-existent unit 0x"
+                      TARGET_FMT_lx "\n", reg);
+        return H_PARAMETER;
+    }
+
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong msg_hi = args[1];
+    target_ulong msg_lo = args[2];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    uint64_t crq_mangle[2];
+
+    if (!dev) {
+        hcall_dprintf("h_send_crq on non-existent unit 0x"
+                      TARGET_FMT_lx "\n", reg);
+        return H_PARAMETER;
+    }
+    crq_mangle[0] = cpu_to_be64(msg_hi);
+    crq_mangle[1] = cpu_to_be64(msg_lo);
+
+    if (dev->crq.SendFunc) {
+        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
+    }
+
+    return H_HARDWARE;
+}
+
+static target_ulong h_enable_crq(CPUState *env, sPAPREnvironment *spapr,
+                                 target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        hcall_dprintf("h_enable_crq on non-existent unit 0x"
+                      TARGET_FMT_lx "\n", reg);
+        return H_PARAMETER;
+    }
+
+    return 0;
+}
+
+/* Returns negative error, 0 success, or positive: queue full */
+int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
+{
+    int rc;
+    uint8_t byte;
+
+    if (!dev->crq.qsize) {
+        fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
+        return -1;
+    }
+
+    /* Maybe do a fast path for KVM just writing to the pages */
+    rc = spapr_tce_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
+    if (rc) {
+        return rc;
+    }
+    if (byte != 0) {
+        return 1;
+    }
+
+    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
+                             &crq[8], 8);
+    if (rc) {
+        return rc;
+    }
+
+    kvmppc_eieio();
+
+    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
+    if (rc) {
+        return rc;
+    }
+
+    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
+
+    if (dev->signal_state & 1) {
+        qemu_irq_pulse(dev->qirq);
+    }
+
+    return 0;
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 {
     VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
@@ -431,6 +585,12 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     /* hcall-tce */
     spapr_register_hypercall(H_PUT_TCE, h_put_tce);
 
+    /* hcall-crq */
+    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
+    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
+    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
+    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
+
     for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
         VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 4cfaf55..ba16795 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -32,10 +32,19 @@ enum VIOsPAPR_TCEAccess {
     SPAPR_TCE_RW = 3,
 };
 
+struct VIOsPAPRDevice;
+
 typedef struct VIOsPAPR_RTCE {
     uint64_t tce;
 } VIOsPAPR_RTCE;
 
+typedef struct VIOsPAPR_CRQ {
+    uint64_t qladdr;
+    uint32_t qsize;
+    uint32_t qnext;
+    int(*SendFunc)(struct VIOsPAPRDevice *vdev, uint8_t *crq);
+} VIOsPAPR_CRQ;
+
 typedef struct VIOsPAPRDevice {
     DeviceState qdev;
     uint32_t reg;
@@ -44,6 +53,7 @@ typedef struct VIOsPAPRDevice {
     target_ulong signal_state;
     uint32_t rtce_window_size;
     VIOsPAPR_RTCE *rtce_table;
+    VIOsPAPR_CRQ crq;
 } VIOsPAPRDevice;
 
 typedef struct VIOsPAPRBus {
@@ -81,6 +91,8 @@ void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val);
 void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val);
 uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
 
+int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
+
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
 void spapr_vty_create(VIOsPAPRBus *bus,
                       uint32_t reg, CharDriverState *chardev,
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 911b19e..5afb308 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -18,6 +18,17 @@ uint32_t kvmppc_get_tbfreq(void);
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
 int kvmppc_set_interrupt(CPUState *env, int irq, int level);
 
+#ifndef CONFIG_KVM
+#define kvmppc_eieio() do { } while (0)
+#else
+#define kvmppc_eieio() \
+    do {                                          \
+        if (kvm_enabled()) {                          \
+            asm volatile("eieio" : : : "memory"); \
+        } \
+    } while (0)
+#endif
+
 #ifndef KVM_INTERRUPT_SET
 #define KVM_INTERRUPT_SET -1
 #endif
commit 8d90ad900507e373a7aa26daacd51e0474760425
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:29 2011 +1100

    Implement sPAPR Virtual LAN (ibmveth)
    
    This patch implements the PAPR specified Inter Virtual Machine Logical
    LAN; that is the virtual hardware used by the Linux ibmveth driver.
    
    Signed-off-by: Paul Mackerras <paulus at samba.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index c795428..cd7bb41 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -234,7 +234,7 @@ obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
 obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-y += xics.o spapr_vty.o
+obj-ppc-y += xics.o spapr_vty.o spapr_llan.o
 endif
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
diff --git a/hw/spapr.c b/hw/spapr.c
index f8749cc..c7306d9 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -27,6 +27,7 @@
 #include "sysemu.h"
 #include "hw.h"
 #include "elf.h"
+#include "net.h"
 
 #include "hw/boards.h"
 #include "hw/ppc.h"
@@ -334,6 +335,24 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         }
     }
 
+    for (i = 0; i < nb_nics; i++, irq++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!nd->model) {
+            nd->model = qemu_strdup("ibmveth");
+        }
+
+        if (strcmp(nd->model, "ibmveth") == 0) {
+            spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd,
+                              xics_find_qirq(spapr->icp, irq), irq);
+        } else {
+            fprintf(stderr, "pSeries (sPAPR) platform does not support "
+                    "NIC model '%s' (only ibmveth is supported)\n",
+                    nd->model);
+            exit(1);
+        }
+    }
+
     if (kernel_filename) {
         uint64_t lowaddr = 0;
 
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
new file mode 100644
index 0000000..1d83fd5
--- /dev/null
+++ b/hw/spapr_llan.c
@@ -0,0 +1,521 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Inter-VM Logical Lan, aka ibmveth
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "hw.h"
+#include "net.h"
+#include "hw/qdev.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+#define ETH_ALEN        6
+#define MAX_PACKET_SIZE 65536
+
+/*#define DEBUG*/
+
+#ifdef DEBUG
+#define dprintf(fmt...) do { fprintf(stderr, fmt); } while (0)
+#else
+#define dprintf(fmt...)
+#endif
+
+/*
+ * Virtual LAN device
+ */
+
+typedef uint64_t vlan_bd_t;
+
+#define VLAN_BD_VALID        0x8000000000000000ULL
+#define VLAN_BD_TOGGLE       0x4000000000000000ULL
+#define VLAN_BD_NO_CSUM      0x0200000000000000ULL
+#define VLAN_BD_CSUM_GOOD    0x0100000000000000ULL
+#define VLAN_BD_LEN_MASK     0x00ffffff00000000ULL
+#define VLAN_BD_LEN(bd)      (((bd) & VLAN_BD_LEN_MASK) >> 32)
+#define VLAN_BD_ADDR_MASK    0x00000000ffffffffULL
+#define VLAN_BD_ADDR(bd)     ((bd) & VLAN_BD_ADDR_MASK)
+
+#define VLAN_VALID_BD(addr, len) (VLAN_BD_VALID | \
+                                  (((len) << 32) & VLAN_BD_LEN_MASK) |  \
+                                  (addr & VLAN_BD_ADDR_MASK))
+
+#define VLAN_RXQC_TOGGLE     0x80
+#define VLAN_RXQC_VALID      0x40
+#define VLAN_RXQC_NO_CSUM    0x02
+#define VLAN_RXQC_CSUM_GOOD  0x01
+
+#define VLAN_RQ_ALIGNMENT    16
+#define VLAN_RXQ_BD_OFF      0
+#define VLAN_FILTER_BD_OFF   8
+#define VLAN_RX_BDS_OFF      16
+#define VLAN_MAX_BUFS        ((SPAPR_VIO_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
+
+typedef struct VIOsPAPRVLANDevice {
+    VIOsPAPRDevice sdev;
+    NICConf nicconf;
+    NICState *nic;
+    int isopen;
+    target_ulong buf_list;
+    int add_buf_ptr, use_buf_ptr, rx_bufs;
+    target_ulong rxq_ptr;
+} VIOsPAPRVLANDevice;
+
+static int spapr_vlan_can_receive(VLANClientState *nc)
+{
+    VIOsPAPRVLANDevice *dev = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    return (dev->isopen && dev->rx_bufs > 0);
+}
+
+static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf,
+                                  size_t size)
+{
+    VIOsPAPRDevice *sdev = DO_UPCAST(NICState, nc, nc)->opaque;
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    vlan_bd_t rxq_bd = ldq_tce(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
+    vlan_bd_t bd;
+    int buf_ptr = dev->use_buf_ptr;
+    uint64_t handle;
+    uint8_t control;
+
+    dprintf("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id,
+            dev->rx_bufs);
+
+    if (!dev->isopen) {
+        return -1;
+    }
+
+    if (!dev->rx_bufs) {
+        return -1;
+    }
+
+    do {
+        buf_ptr += 8;
+        if (buf_ptr >= SPAPR_VIO_TCE_PAGE_SIZE) {
+            buf_ptr = VLAN_RX_BDS_OFF;
+        }
+
+        bd = ldq_tce(sdev, dev->buf_list + buf_ptr);
+        dprintf("use_buf_ptr=%d bd=0x%016llx\n",
+                buf_ptr, (unsigned long long)bd);
+    } while ((!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8)))
+             && (buf_ptr != dev->use_buf_ptr));
+
+    if (!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8))) {
+        /* Failed to find a suitable buffer */
+        return -1;
+    }
+
+    /* Remove the buffer from the pool */
+    dev->rx_bufs--;
+    dev->use_buf_ptr = buf_ptr;
+    stq_tce(sdev, dev->buf_list + dev->use_buf_ptr, 0);
+
+    dprintf("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs);
+
+    /* Transfer the packet data */
+    if (spapr_tce_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) {
+        return -1;
+    }
+
+    dprintf("spapr_vlan_receive: DMA write completed\n");
+
+    /* Update the receive queue */
+    control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID;
+    if (rxq_bd & VLAN_BD_TOGGLE) {
+        control ^= VLAN_RXQC_TOGGLE;
+    }
+
+    handle = ldq_tce(sdev, VLAN_BD_ADDR(bd));
+    stq_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle);
+    stw_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size);
+    sth_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);
+    stb_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);
+
+    dprintf("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",
+            (unsigned long long)dev->rxq_ptr,
+            (unsigned long long)ldq_tce(sdev, VLAN_BD_ADDR(rxq_bd) +
+                                        dev->rxq_ptr),
+            (unsigned long long)ldq_tce(sdev, VLAN_BD_ADDR(rxq_bd) +
+                                        dev->rxq_ptr + 8));
+
+    dev->rxq_ptr += 16;
+    if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) {
+        dev->rxq_ptr = 0;
+        stq_tce(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE);
+    }
+
+    if (sdev->signal_state & 1) {
+        qemu_irq_pulse(sdev->qirq);
+    }
+
+    return size;
+}
+
+static NetClientInfo net_spapr_vlan_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = spapr_vlan_can_receive,
+    .receive = spapr_vlan_receive,
+};
+
+static int spapr_vlan_init(VIOsPAPRDevice *sdev)
+{
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRBus *bus;
+
+    bus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
+
+    qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
+
+    dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
+                            sdev->qdev.info->name, sdev->qdev.id, dev);
+    qemu_format_nic_info_str(&dev->nic->nc, dev->nicconf.macaddr.a);
+
+    return 0;
+}
+
+void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
+                       qemu_irq qirq, uint32_t vio_irq_num)
+{
+    DeviceState *dev;
+    VIOsPAPRDevice *sdev;
+
+    dev = qdev_create(&bus->bus, "spapr-vlan");
+    qdev_prop_set_uint32(dev, "reg", reg);
+
+    qdev_set_nic_properties(dev, nd);
+
+    qdev_init_nofail(dev);
+    sdev = (VIOsPAPRDevice *)dev;
+    sdev->qirq = qirq;
+    sdev->vio_irq_num = vio_irq_num;
+}
+
+static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+{
+    VIOsPAPRVLANDevice *vdev = (VIOsPAPRVLANDevice *)dev;
+    uint8_t padded_mac[8] = {0, 0};
+    int ret;
+
+    /* Some old phyp versions give the mac address in an 8-byte
+     * property.  The kernel driver has an insane workaround for this;
+     * rather than doing the obvious thing and checking the property
+     * length, it checks whether the first byte has 0b10 in the low
+     * bits.  If a correct 6-byte property has a different first byte
+     * the kernel will get the wrong mac address, overrunning its
+     * buffer in the process (read only, thank goodness).
+     *
+     * Here we workaround the kernel workaround by always supplying an
+     * 8-byte property, with the mac address in the last six bytes */
+    memcpy(&padded_mac[2], &vdev->nicconf.macaddr, ETH_ALEN);
+    ret = fdt_setprop(fdt, node_off, "local-mac-address",
+                      padded_mac, sizeof(padded_mac));
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,mac-address-filters", 0);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd,
+                    target_ulong alignment)
+{
+    if ((VLAN_BD_ADDR(bd) % alignment)
+        || (VLAN_BD_LEN(bd) % alignment)) {
+        return -1;
+    }
+
+    if (spapr_vio_check_tces(&dev->sdev, VLAN_BD_ADDR(bd),
+                             VLAN_BD_LEN(bd), SPAPR_TCE_RW) != 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static target_ulong h_register_logical_lan(CPUState *env,
+                                           sPAPREnvironment *spapr,
+                                           target_ulong opcode,
+                                           target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong buf_list = args[1];
+    target_ulong rec_queue = args[2];
+    target_ulong filter_list = args[3];
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    vlan_bd_t filter_list_bd;
+#ifdef DEBUG
+    target_ulong mac_address = args[4];
+#endif
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    if (dev->isopen) {
+        hcall_dprintf("H_REGISTER_LOGICAL_LAN called twice without "
+                      "H_FREE_LOGICAL_LAN\n");
+        return H_RESOURCE;
+    }
+
+    if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_VIO_TCE_PAGE_SIZE),
+                 SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
+        hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx " for "
+                      "H_REGISTER_LOGICAL_LAN\n", buf_list);
+        return H_PARAMETER;
+    }
+
+    filter_list_bd = VLAN_VALID_BD(filter_list, SPAPR_VIO_TCE_PAGE_SIZE);
+    if (check_bd(dev, filter_list_bd, SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
+        hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx " for "
+                      "H_REGISTER_LOGICAL_LAN\n", filter_list);
+        return H_PARAMETER;
+    }
+
+    if (!(rec_queue & VLAN_BD_VALID)
+        || (check_bd(dev, rec_queue, VLAN_RQ_ALIGNMENT) < 0)) {
+        hcall_dprintf("Bad receive queue for H_REGISTER_LOGICAL_LAN\n");
+        return H_PARAMETER;
+    }
+
+    dev->buf_list = buf_list;
+    sdev->signal_state = 0;
+
+    rec_queue &= ~VLAN_BD_TOGGLE;
+
+    /* Initialize the buffer list */
+    stq_tce(sdev, buf_list, rec_queue);
+    stq_tce(sdev, buf_list + 8, filter_list_bd);
+    spapr_tce_dma_zero(sdev, buf_list + VLAN_RX_BDS_OFF,
+                       SPAPR_VIO_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF);
+    dev->add_buf_ptr = VLAN_RX_BDS_OFF - 8;
+    dev->use_buf_ptr = VLAN_RX_BDS_OFF - 8;
+    dev->rx_bufs = 0;
+    dev->rxq_ptr = 0;
+
+    /* Initialize the receive queue */
+    spapr_tce_dma_zero(sdev, VLAN_BD_ADDR(rec_queue), VLAN_BD_LEN(rec_queue));
+
+    dev->isopen = 1;
+    return H_SUCCESS;
+}
+
+
+static target_ulong h_free_logical_lan(CPUState *env, sPAPREnvironment *spapr,
+                                       target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    if (!dev->isopen) {
+        hcall_dprintf("H_FREE_LOGICAL_LAN called without "
+                      "H_REGISTER_LOGICAL_LAN\n");
+        return H_RESOURCE;
+    }
+
+    dev->buf_list = 0;
+    dev->rx_bufs = 0;
+    dev->isopen = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong h_add_logical_lan_buffer(CPUState *env,
+                                             sPAPREnvironment *spapr,
+                                             target_ulong opcode,
+                                             target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong buf = args[1];
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    vlan_bd_t bd;
+
+    dprintf("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
+            ", 0x" TARGET_FMT_lx ")\n", reg, buf);
+
+    if (!sdev) {
+        hcall_dprintf("Wrong device in h_add_logical_lan_buffer\n");
+        return H_PARAMETER;
+    }
+
+    if ((check_bd(dev, buf, 4) < 0)
+        || (VLAN_BD_LEN(buf) < 16)) {
+        hcall_dprintf("Bad buffer enqueued in h_add_logical_lan_buffer\n");
+        return H_PARAMETER;
+    }
+
+    if (!dev->isopen || dev->rx_bufs >= VLAN_MAX_BUFS) {
+        return H_RESOURCE;
+    }
+
+    do {
+        dev->add_buf_ptr += 8;
+        if (dev->add_buf_ptr >= SPAPR_VIO_TCE_PAGE_SIZE) {
+            dev->add_buf_ptr = VLAN_RX_BDS_OFF;
+        }
+
+        bd = ldq_tce(sdev, dev->buf_list + dev->add_buf_ptr);
+    } while (bd & VLAN_BD_VALID);
+
+    stq_tce(sdev, dev->buf_list + dev->add_buf_ptr, buf);
+
+    dev->rx_bufs++;
+
+    dprintf("h_add_logical_lan_buffer():  Added buf  ptr=%d  rx_bufs=%d"
+            " bd=0x%016llx\n", dev->add_buf_ptr, dev->rx_bufs,
+            (unsigned long long)buf);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_send_logical_lan(CPUState *env, sPAPREnvironment *spapr,
+                                       target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong *bufs = args + 1;
+    target_ulong continue_token = args[7];
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    unsigned total_len;
+    uint8_t *lbuf, *p;
+    int i, nbufs;
+    int ret;
+
+    dprintf("H_SEND_LOGICAL_LAN(0x" TARGET_FMT_lx ", <bufs>, 0x"
+            TARGET_FMT_lx ")\n", reg, continue_token);
+
+    if (!sdev) {
+        return H_PARAMETER;
+    }
+
+    dprintf("rxbufs = %d\n", dev->rx_bufs);
+
+    if (!dev->isopen) {
+        return H_DROPPED;
+    }
+
+    if (continue_token) {
+        return H_HARDWARE; /* FIXME actually handle this */
+    }
+
+    total_len = 0;
+    for (i = 0; i < 6; i++) {
+        dprintf("   buf desc: 0x" TARGET_FMT_lx "\n", bufs[i]);
+        if (!(bufs[i] & VLAN_BD_VALID)) {
+            break;
+        }
+        total_len += VLAN_BD_LEN(bufs[i]);
+    }
+
+    nbufs = i;
+    dprintf("h_send_logical_lan() %d buffers, total length 0x%x\n",
+            nbufs, total_len);
+
+    if (total_len == 0) {
+        return H_SUCCESS;
+    }
+
+    if (total_len > MAX_PACKET_SIZE) {
+        /* Don't let the guest force too large an allocation */
+        return H_RESOURCE;
+    }
+
+    lbuf = alloca(total_len);
+    p = lbuf;
+    for (i = 0; i < nbufs; i++) {
+        ret = spapr_tce_dma_read(sdev, VLAN_BD_ADDR(bufs[i]),
+                                 p, VLAN_BD_LEN(bufs[i]));
+        if (ret < 0) {
+            return ret;
+        }
+
+        p += VLAN_BD_LEN(bufs[i]);
+    }
+
+    qemu_send_packet(&dev->nic->nc, lbuf, total_len);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
+                                     target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    return H_SUCCESS;
+}
+
+static void vlan_hcalls(VIOsPAPRBus *bus)
+{
+    spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
+    spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
+    spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
+    spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
+                             h_add_logical_lan_buffer);
+    spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
+}
+
+static VIOsPAPRDeviceInfo spapr_vlan = {
+    .init = spapr_vlan_init,
+    .devnode = spapr_vlan_devnode,
+    .dt_name = "l-lan",
+    .dt_type = "network",
+    .dt_compatible = "IBM,l-lan",
+    .signal_mask = 0x1,
+    .hcalls = vlan_hcalls,
+    .qdev.name = "spapr-vlan",
+    .qdev.size = sizeof(VIOsPAPRVLANDevice),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0x1000),
+        DEFINE_PROP_UINT32("dma-window", VIOsPAPRDevice, rtce_window_size,
+                           0x10000000),
+        DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void spapr_vlan_register(void)
+{
+    spapr_vio_bus_register_withprop(&spapr_vlan);
+}
+device_init(spapr_vlan_register);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 9d864c2..4cfaf55 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -86,4 +86,7 @@ void spapr_vty_create(VIOsPAPRBus *bus,
                       uint32_t reg, CharDriverState *chardev,
                       qemu_irq qirq, uint32_t vio_irq_num);
 
+void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
+                       qemu_irq qirq, uint32_t vio_irq_num);
+
 #endif /* _HW_SPAPR_VIO_H */
commit ee86dfeebb5c12372935374b32e796e5d2544c90
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:28 2011 +1100

    Implement TCE translation for sPAPR VIO
    
    This patch implements the necessary infrastructure and hypercalls for
    sPAPR's TCE (Translation Control Entry) IOMMU mechanism.  This is necessary
    for all virtual IO devices which do DMA (i.e. nearly all of them).
    
    Signed-off-by: Ben Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 859cf86..f8749cc 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -65,7 +65,8 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
-    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt";
+    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
+        "\0hcall-tce";
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 605079c..39d77ee 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -37,6 +37,7 @@
 #endif /* CONFIG_FDT */
 
 /* #define DEBUG_SPAPR */
+/* #define DEBUG_TCE */
 
 #ifdef DEBUG_SPAPR
 #define dprintf(fmt, ...) \
@@ -115,6 +116,28 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
         }
     }
 
+    if (dev->rtce_window_size) {
+        uint32_t dma_prop[] = {cpu_to_be32(dev->reg),
+                               0, 0,
+                               0, cpu_to_be32(dev->rtce_window_size)};
+
+        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
+        if (ret < 0) {
+            return ret;
+        }
+
+        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
+        if (ret < 0) {
+            return ret;
+        }
+
+        ret = fdt_setprop(fdt, node_off, "ibm,my-dma-window", dma_prop,
+                          sizeof(dma_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
     if (info->devnode) {
         ret = (info->devnode)(dev, fdt, node_off);
         if (ret < 0) {
@@ -126,6 +149,216 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
 }
 #endif /* CONFIG_FDT */
 
+/*
+ * RTCE handling
+ */
+
+static void rtce_init(VIOsPAPRDevice *dev)
+{
+    size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
+        * sizeof(VIOsPAPR_RTCE);
+
+    if (size) {
+        dev->rtce_table = qemu_mallocz(size);
+    }
+}
+
+static target_ulong h_put_tce(CPUState *env, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong liobn = args[0];
+    target_ulong ioba = args[1];
+    target_ulong tce = args[2];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, liobn);
+    VIOsPAPR_RTCE *rtce;
+
+    if (!dev) {
+        hcall_dprintf("spapr_vio_put_tce on non-existent LIOBN "
+                      TARGET_FMT_lx "\n", liobn);
+        return H_PARAMETER;
+    }
+
+    ioba &= ~(SPAPR_VIO_TCE_PAGE_SIZE - 1);
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_vio_put_tce on %s  ioba 0x" TARGET_FMT_lx
+            "  TCE 0x" TARGET_FMT_lx "\n", dev->qdev.id, ioba, tce);
+#endif
+
+    if (ioba >= dev->rtce_window_size) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
+                      TARGET_FMT_lx "\n", ioba);
+        return H_PARAMETER;
+    }
+
+    rtce = dev->rtce_table + (ioba >> SPAPR_VIO_TCE_PAGE_SHIFT);
+    rtce->tce = tce;
+
+    return H_SUCCESS;
+}
+
+int spapr_vio_check_tces(VIOsPAPRDevice *dev, target_ulong ioba,
+                         target_ulong len, enum VIOsPAPR_TCEAccess access)
+{
+    int start, end, i;
+
+    start = ioba >> SPAPR_VIO_TCE_PAGE_SHIFT;
+    end = (ioba + len - 1) >> SPAPR_VIO_TCE_PAGE_SHIFT;
+
+    for (i = start; i <= end; i++) {
+        if ((dev->rtce_table[i].tce & access) != access) {
+#ifdef DEBUG_TCE
+            fprintf(stderr, "FAIL on %d\n", i);
+#endif
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr, const void *buf,
+                        uint32_t size)
+{
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
+            (unsigned long long)taddr, size);
+#endif
+
+    while (size) {
+        uint64_t tce;
+        uint32_t lsize;
+        uint64_t txaddr;
+
+        /* Check if we are in bound */
+        if (taddr >= dev->rtce_window_size) {
+#ifdef DEBUG_TCE
+            fprintf(stderr, "spapr_tce_dma_write out of bounds\n");
+#endif
+            return H_DEST_PARM;
+        }
+        tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
+
+        /* How much til end of page ? */
+        lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
+
+        /* Check TCE */
+        if (!(tce & 2)) {
+            return H_DEST_PARM;
+        }
+
+        /* Translate */
+        txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
+            (taddr & SPAPR_VIO_TCE_PAGE_MASK);
+
+#ifdef DEBUG_TCE
+        fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
+                (unsigned long long)txaddr, lsize);
+#endif
+
+        /* Do it */
+        cpu_physical_memory_write(txaddr, buf, lsize);
+        buf += lsize;
+        taddr += lsize;
+        size -= lsize;
+    }
+    return 0;
+}
+
+int spapr_tce_dma_zero(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size)
+{
+    /* FIXME: allocating a temp buffer is nasty, but just stepping
+     * through writing zeroes is awkward.  This will do for now. */
+    uint8_t zeroes[size];
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_tce_dma_zero taddr=0x%llx size=0x%x\n",
+            (unsigned long long)taddr, size);
+#endif
+
+    memset(zeroes, 0, size);
+    return spapr_tce_dma_write(dev, taddr, zeroes, size);
+}
+
+void stb_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint8_t val)
+{
+    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
+}
+
+void sth_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint16_t val)
+{
+    val = tswap16(val);
+    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
+}
+
+
+void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val)
+{
+    val = tswap32(val);
+    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
+}
+
+void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val)
+{
+    val = tswap64(val);
+    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
+}
+
+int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr, void *buf,
+                       uint32_t size)
+{
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
+            (unsigned long long)taddr, size);
+#endif
+
+    while (size) {
+        uint64_t tce;
+        uint32_t lsize;
+        uint64_t txaddr;
+
+        /* Check if we are in bound */
+        if (taddr >= dev->rtce_window_size) {
+#ifdef DEBUG_TCE
+            fprintf(stderr, "spapr_tce_dma_read out of bounds\n");
+#endif
+            return H_DEST_PARM;
+        }
+        tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
+
+        /* How much til end of page ? */
+        lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
+
+        /* Check TCE */
+        if (!(tce & 1)) {
+            return H_DEST_PARM;
+        }
+
+        /* Translate */
+        txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
+            (taddr & SPAPR_VIO_TCE_PAGE_MASK);
+
+#ifdef DEBUG_TCE
+        fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
+                (unsigned long long)txaddr, lsize);
+#endif
+        /* Do it */
+        cpu_physical_memory_read(txaddr, buf, lsize);
+        buf += lsize;
+        taddr += lsize;
+        size -= lsize;
+    }
+    return H_SUCCESS;
+}
+
+uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr)
+{
+    uint64_t val;
+
+    spapr_tce_dma_read(dev, taddr, &val, sizeof(val));
+    return tswap64(val);
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 {
     VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
@@ -138,6 +371,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 
     dev->qdev.id = id;
 
+    rtce_init(dev);
+
     return info->init(dev);
 }
 
@@ -193,6 +428,9 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     /* hcall-vio */
     spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
 
+    /* hcall-tce */
+    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
+
     for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
         VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 2013927..9d864c2 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -21,12 +21,29 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#define SPAPR_VIO_TCE_PAGE_SHIFT   12
+#define SPAPR_VIO_TCE_PAGE_SIZE    (1ULL << SPAPR_VIO_TCE_PAGE_SHIFT)
+#define SPAPR_VIO_TCE_PAGE_MASK    (SPAPR_VIO_TCE_PAGE_SIZE - 1)
+
+enum VIOsPAPR_TCEAccess {
+    SPAPR_TCE_FAULT = 0,
+    SPAPR_TCE_RO = 1,
+    SPAPR_TCE_WO = 2,
+    SPAPR_TCE_RW = 3,
+};
+
+typedef struct VIOsPAPR_RTCE {
+    uint64_t tce;
+} VIOsPAPR_RTCE;
+
 typedef struct VIOsPAPRDevice {
     DeviceState qdev;
     uint32_t reg;
     qemu_irq qirq;
     uint32_t vio_irq_num;
     target_ulong signal_state;
+    uint32_t rtce_window_size;
+    VIOsPAPR_RTCE *rtce_table;
 } VIOsPAPRDevice;
 
 typedef struct VIOsPAPRBus {
@@ -49,6 +66,21 @@ extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
 
 extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
 
+int spapr_vio_check_tces(VIOsPAPRDevice *dev, target_ulong ioba,
+                         target_ulong len,
+                         enum VIOsPAPR_TCEAccess access);
+
+int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
+                       void *buf, uint32_t size);
+int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
+                        const void *buf, uint32_t size);
+int spapr_tce_dma_zero(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size);
+void stb_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint8_t val);
+void sth_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint16_t val);
+void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val);
+void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val);
+uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
+
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
 void spapr_vty_create(VIOsPAPRBus *bus,
                       uint32_t reg, CharDriverState *chardev,
commit 0201e2da65b1828937c478fa1ac52e58522a32c1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:27 2011 +1100

    Add (virtual) interrupt to PAPR virtual tty device
    
    Now that we have implemented the PAPR "xics" virtualized interrupt
    controller, we can add interrupts in PAPR VIO devices.  This patch adds
    interrupt support to the PAPR virtual tty/console device.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index 200617b..859cf86 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -262,6 +262,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     long pteg_shift = 17;
     int fdt_size;
     char *filename;
+    int irq = 16;
 
     spapr = qemu_malloc(sizeof(*spapr));
     cpu_ppc_hypercall = emulate_spapr_hypercall;
@@ -325,9 +326,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
 
-    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
+    for (i = 0; i < MAX_SERIAL_PORTS; i++, irq++) {
         if (serial_hds[i]) {
-            spapr_vty_create(spapr->vio_bus, i, serial_hds[i]);
+            spapr_vty_create(spapr->vio_bus, i, serial_hds[i],
+                             xics_find_qirq(spapr->icp, irq), irq);
         }
     }
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 8a000c6..2013927 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -51,6 +51,7 @@ extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
 
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
 void spapr_vty_create(VIOsPAPRBus *bus,
-                      uint32_t reg, CharDriverState *chardev);
+                      uint32_t reg, CharDriverState *chardev,
+                      qemu_irq qirq, uint32_t vio_irq_num);
 
 #endif /* _HW_SPAPR_VIO_H */
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index b4da6a8..6fc0105 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -24,6 +24,10 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size)
     VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
     int i;
 
+    if ((dev->in == dev->out) && size) {
+        /* toggle line to simulate edge interrupt */
+        qemu_irq_pulse(dev->sdev.qirq);
+    }
     for (i = 0; i < size; i++) {
         assert((dev->in - dev->out) < VTERM_BUFSIZE);
         dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
@@ -112,14 +116,19 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
 }
 
 void spapr_vty_create(VIOsPAPRBus *bus,
-                      uint32_t reg, CharDriverState *chardev)
+                      uint32_t reg, CharDriverState *chardev,
+                      qemu_irq qirq, uint32_t vio_irq_num)
 {
     DeviceState *dev;
+    VIOsPAPRDevice *sdev;
 
     dev = qdev_create(&bus->bus, "spapr-vty");
     qdev_prop_set_uint32(dev, "reg", reg);
     qdev_prop_set_chr(dev, "chardev", chardev);
     qdev_init_nofail(dev);
+    sdev = (VIOsPAPRDevice *)dev;
+    sdev->qirq = qirq;
+    sdev->vio_irq_num = vio_irq_num;
 }
 
 static void vty_hcalls(VIOsPAPRBus *bus)
commit 00dc738d8a08fce0f0d327e081bb2bd7b6fba888
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:26 2011 +1100

    Add PAPR H_VIO_SIGNAL hypercall and infrastructure for VIO interrupts
    
    This patch adds infrastructure to support interrupts from PAPR virtual IO
    devices.  This includes correctly advertising those interrupts in the
    device tree, and implementing the H_VIO_SIGNAL hypercall, used to
    enable and disable individual device interrupts.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index b5aefd7..200617b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -65,7 +65,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
-    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr";
+    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt";
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 10acb4c..605079c 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -105,6 +105,16 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
         }
     }
 
+    if (dev->qirq) {
+        uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0};
+
+        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
+                          sizeof(ints_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
     if (info->devnode) {
         ret = (info->devnode)(dev, fdt, node_off);
         if (ret < 0) {
@@ -140,6 +150,30 @@ void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info)
     qdev_register(&info->qdev);
 }
 
+static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr,
+                                 target_ulong opcode,
+                                 target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong mode = args[1];
+    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    VIOsPAPRDeviceInfo *info;
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+
+    if (mode & ~info->signal_mask) {
+        return H_PARAMETER;
+    }
+
+    dev->signal_state = mode;
+
+    return H_SUCCESS;
+}
+
 VIOsPAPRBus *spapr_vio_bus_init(void)
 {
     VIOsPAPRBus *bus;
@@ -156,6 +190,9 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
     qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
     bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
 
+    /* hcall-vio */
+    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
+
     for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
         VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index b164ad3..8a000c6 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -24,6 +24,9 @@
 typedef struct VIOsPAPRDevice {
     DeviceState qdev;
     uint32_t reg;
+    qemu_irq qirq;
+    uint32_t vio_irq_num;
+    target_ulong signal_state;
 } VIOsPAPRDevice;
 
 typedef struct VIOsPAPRBus {
@@ -33,6 +36,7 @@ typedef struct VIOsPAPRBus {
 typedef struct {
     DeviceInfo qdev;
     const char *dt_name, *dt_type, *dt_compatible;
+    target_ulong signal_mask;
     int (*init)(VIOsPAPRDevice *dev);
     void (*hcalls)(VIOsPAPRBus *bus);
     int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
@@ -43,6 +47,8 @@ extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
 extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
 extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
 
+extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
+
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
 void spapr_vty_create(VIOsPAPRBus *bus,
                       uint32_t reg, CharDriverState *chardev);
commit b5cec4c5f294ca3af24e7edf4f37cc2de0ae0e03
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:25 2011 +1100

    Implement the PAPR (pSeries) virtualized interrupt controller (xics)
    
    PAPR defines an interrupt control architecture which is logically divided
    into ICS (Interrupt Control Presentation, each unit is responsible for
    presenting interrupts to a particular "interrupt server", i.e. CPU) and
    ICS (Interrupt Control Source, each unit responsible for one or more
    hardware interrupts as numbered globally across the system).  All PAPR
    virtual IO devices expect to deliver interrupts via this mechanism.  In
    Linux, this interrupt controller system is handled by the "xics" driver.
    
    On pSeries systems, access to the interrupt controller is virtualized via
    hypercalls and RTAS methods.  However, the virtualized interface is very
    similar to the underlying interrupt controller hardware, and similar PICs
    exist un-virtualized in some other systems.
    
    This patch implements both the ICP and ICS sides of the PAPR interrupt
    controller.  For now, only the hypercall virtualized interface is provided,
    however it would be relatively straightforward to graft an emulated
    register interface onto the underlying interrupt logic if we want to add
    a machine with a hardware ICS/ICP system in the future.
    
    There are some limitations in this implementation: it is assumed for now
    that only one instance of the ICS exists, although a full xics system can
    have several, each responsible for a different group of hardware irqs.
    ICP/ICS can handle both level-sensitve (LSI) and message signalled (MSI)
    interrupt inputs.  For now, this implementation supports only MSI
    interrupts, since that is used by PAPR virtual IO devices.
    
    Signed-off-by: Paul Mackerras <paulus at samba.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index a53d99f..c795428 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -234,7 +234,7 @@ obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
 obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-y += spapr_vty.o
+obj-ppc-y += xics.o spapr_vty.o
 endif
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
diff --git a/hw/spapr.c b/hw/spapr.c
index 6c64de8..b5aefd7 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -34,6 +34,7 @@
 
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
+#include "hw/xics.h"
 
 #include <libfdt.h>
 
@@ -45,6 +46,7 @@
 #define TIMEBASE_FREQ           512000000ULL
 
 #define MAX_CPUS                32
+#define XICS_IRQS		1024
 
 sPAPREnvironment *spapr;
 
@@ -64,6 +66,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
     char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr";
+    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
     int ret;
@@ -125,6 +128,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
     for (i = 0; i < smp_cpus; i++) {
         CPUState *env = envs[i];
+        uint32_t gserver_prop[] = {cpu_to_be32(i), 0}; /* HACK! */
         char *nodename;
         uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                            0xffffffff, 0xffffffff};
@@ -155,6 +159,9 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                            pft_size_prop, sizeof(pft_size_prop))));
         _FDT((fdt_property_string(fdt, "status", "okay")));
         _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
+        _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", i)));
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+                           gserver_prop, sizeof(gserver_prop))));
 
         if (envs[i]->mmu_model & POWERPC_MMU_1TSEG) {
             _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
@@ -176,6 +183,20 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
     _FDT((fdt_end_node(fdt)));
 
+    /* interrupt controller */
+    _FDT((fdt_begin_node(fdt, "interrupt-controller at 0")));
+
+    _FDT((fdt_property_string(fdt, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
+    _FDT((fdt_property_cell(fdt, "reg", 0)));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+                       interrupt_server_ranges_prop,
+                       sizeof(interrupt_server_ranges_prop))));
+
+    _FDT((fdt_end_node(fdt)));
+
     /* vdevice */
     _FDT((fdt_begin_node(fdt, "vdevice")));
 
@@ -183,6 +204,8 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
     _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
     _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
 
     _FDT((fdt_end_node(fdt)));
 
@@ -296,6 +319,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
     qemu_free(filename);
 
+    /* Set up Interrupt Controller */
+    spapr->icp = xics_system_init(smp_cpus, envs, XICS_IRQS);
+
+    /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
 
     for (i = 0; i < MAX_SERIAL_PORTS; i++) {
diff --git a/hw/spapr.h b/hw/spapr.h
index 0dcb83a..fae8e13 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -2,9 +2,11 @@
 #define __HW_SPAPR_H__
 
 struct VIOsPAPRBus;
+struct icp_state;
 
 typedef struct sPAPREnvironment {
     struct VIOsPAPRBus *vio_bus;
+    struct icp_state *icp;
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
diff --git a/hw/xics.c b/hw/xics.c
new file mode 100644
index 0000000..66047a6
--- /dev/null
+++ b/hw/xics.c
@@ -0,0 +1,486 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "hw.h"
+#include "hw/spapr.h"
+#include "hw/xics.h"
+
+#include <pthread.h>
+
+/*
+ * ICP: Presentation layer
+ */
+
+struct icp_server_state {
+    uint32_t xirr;
+    uint8_t pending_priority;
+    uint8_t mfrr;
+    qemu_irq output;
+};
+
+#define XISR_MASK  0x00ffffff
+#define CPPR_MASK  0xff000000
+
+#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
+#define CPPR(ss)   (((ss)->xirr) >> 24)
+
+struct ics_state;
+
+struct icp_state {
+    long nr_servers;
+    struct icp_server_state *ss;
+    struct ics_state *ics;
+};
+
+static void ics_reject(struct ics_state *ics, int nr);
+static void ics_resend(struct ics_state *ics);
+static void ics_eoi(struct ics_state *ics, int nr);
+
+static void icp_check_ipi(struct icp_state *icp, int server)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
+        return;
+    }
+
+    if (XISR(ss)) {
+        ics_reject(icp->ics, XISR(ss));
+    }
+
+    ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
+    ss->pending_priority = ss->mfrr;
+    qemu_irq_raise(ss->output);
+}
+
+static void icp_resend(struct icp_state *icp, int server)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    if (ss->mfrr < CPPR(ss)) {
+        icp_check_ipi(icp, server);
+    }
+    ics_resend(icp->ics);
+}
+
+static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+    uint8_t old_cppr;
+    uint32_t old_xisr;
+
+    old_cppr = CPPR(ss);
+    ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
+
+    if (cppr < old_cppr) {
+        if (XISR(ss) && (cppr <= ss->pending_priority)) {
+            old_xisr = XISR(ss);
+            ss->xirr &= ~XISR_MASK; /* Clear XISR */
+            qemu_irq_lower(ss->output);
+            ics_reject(icp->ics, old_xisr);
+        }
+    } else {
+        if (!XISR(ss)) {
+            icp_resend(icp, server);
+        }
+    }
+}
+
+static void icp_set_mfrr(struct icp_state *icp, int nr, uint8_t mfrr)
+{
+    struct icp_server_state *ss = icp->ss + nr;
+
+    ss->mfrr = mfrr;
+    if (mfrr < CPPR(ss)) {
+        icp_check_ipi(icp, nr);
+    }
+}
+
+static uint32_t icp_accept(struct icp_server_state *ss)
+{
+    uint32_t xirr;
+
+    qemu_irq_lower(ss->output);
+    xirr = ss->xirr;
+    ss->xirr = ss->pending_priority << 24;
+    return xirr;
+}
+
+static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    ics_eoi(icp->ics, xirr & XISR_MASK);
+    /* Send EOI -> ICS */
+    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+    if (!XISR(ss)) {
+        icp_resend(icp, server);
+    }
+}
+
+static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    if ((priority >= CPPR(ss))
+        || (XISR(ss) && (ss->pending_priority <= priority))) {
+        ics_reject(icp->ics, nr);
+    } else {
+        if (XISR(ss)) {
+            ics_reject(icp->ics, XISR(ss));
+        }
+        ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
+        ss->pending_priority = priority;
+        qemu_irq_raise(ss->output);
+    }
+}
+
+/*
+ * ICS: Source layer
+ */
+
+struct ics_irq_state {
+    int server;
+    uint8_t priority;
+    uint8_t saved_priority;
+    /* int pending:1; */
+    /* int presented:1; */
+    int rejected:1;
+    int masked_pending:1;
+};
+
+struct ics_state {
+    int nr_irqs;
+    int offset;
+    qemu_irq *qirqs;
+    struct ics_irq_state *irqs;
+    struct icp_state *icp;
+};
+
+static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
+{
+    return (nr >= ics->offset)
+        && (nr < (ics->offset + ics->nr_irqs));
+}
+
+static void ics_set_irq_msi(void *opaque, int nr, int val)
+{
+    struct ics_state *ics = (struct ics_state *)opaque;
+    struct ics_irq_state *irq = ics->irqs + nr;
+
+    if (val) {
+        if (irq->priority == 0xff) {
+            irq->masked_pending = 1;
+            /* masked pending */ ;
+        } else  {
+            icp_irq(ics->icp, irq->server, nr + ics->offset, irq->priority);
+        }
+    }
+}
+
+static void ics_reject_msi(struct ics_state *ics, int nr)
+{
+    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+    irq->rejected = 1;
+}
+
+static void ics_resend_msi(struct ics_state *ics)
+{
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        struct ics_irq_state *irq = ics->irqs + i;
+
+        /* FIXME: filter by server#? */
+        if (irq->rejected) {
+            irq->rejected = 0;
+            if (irq->priority != 0xff) {
+                icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority);
+            }
+        }
+    }
+}
+
+static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
+                               uint8_t priority)
+{
+    struct ics_irq_state *irq = ics->irqs + nr;
+
+    irq->server = server;
+    irq->priority = priority;
+
+    if (!irq->masked_pending || (priority == 0xff)) {
+        return;
+    }
+
+    irq->masked_pending = 0;
+    icp_irq(ics->icp, server, nr + ics->offset, priority);
+}
+
+static void ics_reject(struct ics_state *ics, int nr)
+{
+    ics_reject_msi(ics, nr);
+}
+
+static void ics_resend(struct ics_state *ics)
+{
+    ics_resend_msi(ics);
+}
+
+static void ics_eoi(struct ics_state *ics, int nr)
+{
+}
+
+/*
+ * Exported functions
+ */
+
+qemu_irq xics_find_qirq(struct icp_state *icp, int irq)
+{
+    if ((irq < icp->ics->offset)
+        || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) {
+        return NULL;
+    }
+
+    return icp->ics->qirqs[irq - icp->ics->offset];
+}
+
+static target_ulong h_cppr(CPUState *env, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    target_ulong cppr = args[0];
+
+    icp_set_cppr(spapr->icp, env->cpu_index, cppr);
+    return H_SUCCESS;
+}
+
+static target_ulong h_ipi(CPUState *env, sPAPREnvironment *spapr,
+                          target_ulong opcode, target_ulong *args)
+{
+    target_ulong server = args[0];
+    target_ulong mfrr = args[1];
+
+    if (server >= spapr->icp->nr_servers) {
+        return H_PARAMETER;
+    }
+
+    icp_set_mfrr(spapr->icp, server, mfrr);
+    return H_SUCCESS;
+
+}
+
+static target_ulong h_xirr(CPUState *env, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index);
+
+    args[0] = xirr;
+    return H_SUCCESS;
+}
+
+static target_ulong h_eoi(CPUState *env, sPAPREnvironment *spapr,
+                          target_ulong opcode, target_ulong *args)
+{
+    target_ulong xirr = args[0];
+
+    icp_eoi(spapr->icp, env->cpu_index, xirr);
+    return H_SUCCESS;
+}
+
+static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
+                          uint32_t nargs, target_ulong args,
+                          uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr, server, priority;
+
+    if ((nargs != 3) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+    server = rtas_ld(args, 1);
+    priority = rtas_ld(args, 2);
+
+    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
+        || (priority > 0xff)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    ics_write_xive_msi(ics, nr - ics->offset, server, priority);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
+                          uint32_t nargs, target_ulong args,
+                          uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 3)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    rtas_st(rets, 0, 0); /* Success */
+    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
+    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+}
+
+static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
+                         uint32_t nargs, target_ulong args,
+                         uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    /* This is a NOP for now, since the described PAPR semantics don't
+     * seem to gel with what Linux does */
+#if 0
+    struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
+
+    irq->saved_priority = irq->priority;
+    ics_write_xive_msi(xics, nr - xics->offset, irq->server, 0xff);
+#endif
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
+                        uint32_t nargs, target_ulong args,
+                        uint32_t nret, target_ulong rets)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    uint32_t nr;
+
+    if ((nargs != 1) || (nret != 1)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    nr = rtas_ld(args, 0);
+
+    if (!ics_valid_irq(ics, nr)) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    /* This is a NOP for now, since the described PAPR semantics don't
+     * seem to gel with what Linux does */
+#if 0
+    struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
+
+    ics_write_xive_msi(xics, nr - xics->offset,
+                       irq->server, irq->saved_priority);
+#endif
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+struct icp_state *xics_system_init(int nr_servers, CPUState *servers[],
+                                   int nr_irqs)
+{
+    int i;
+    struct icp_state *icp;
+    struct ics_state *ics;
+
+    icp = qemu_mallocz(sizeof(*icp));
+    icp->nr_servers = nr_servers;
+    icp->ss = qemu_mallocz(nr_servers * sizeof(struct icp_server_state));
+
+    for (i = 0; i < nr_servers; i++) {
+        servers[i]->cpu_index = i;
+
+        switch (PPC_INPUT(servers[i])) {
+        case PPC_FLAGS_INPUT_POWER7:
+            icp->ss[i].output = servers[i]->irq_inputs[POWER7_INPUT_INT];
+            break;
+
+        case PPC_FLAGS_INPUT_970:
+            icp->ss[i].output = servers[i]->irq_inputs[PPC970_INPUT_INT];
+            break;
+
+        default:
+            hw_error("XICS interrupt model does not support this CPU bus "
+                     "model\n");
+            exit(1);
+        }
+
+        icp->ss[i].mfrr = 0xff;
+    }
+
+    ics = qemu_mallocz(sizeof(*ics));
+    ics->nr_irqs = nr_irqs;
+    ics->offset = 16;
+    ics->irqs = qemu_mallocz(nr_irqs * sizeof(struct ics_irq_state));
+
+    icp->ics = ics;
+    ics->icp = icp;
+
+    for (i = 0; i < nr_irqs; i++) {
+        ics->irqs[i].priority = 0xff;
+        ics->irqs[i].saved_priority = 0xff;
+    }
+
+    ics->qirqs = qemu_allocate_irqs(ics_set_irq_msi, ics, nr_irqs);
+
+    spapr_register_hypercall(H_CPPR, h_cppr);
+    spapr_register_hypercall(H_IPI, h_ipi);
+    spapr_register_hypercall(H_XIRR, h_xirr);
+    spapr_register_hypercall(H_EOI, h_eoi);
+
+    spapr_rtas_register("ibm,set-xive", rtas_set_xive);
+    spapr_rtas_register("ibm,get-xive", rtas_get_xive);
+    spapr_rtas_register("ibm,int-off", rtas_int_off);
+    spapr_rtas_register("ibm,int-on", rtas_int_on);
+
+    return icp;
+}
diff --git a/hw/xics.h b/hw/xics.h
new file mode 100644
index 0000000..096eeb3
--- /dev/null
+++ b/hw/xics.h
@@ -0,0 +1,39 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#if !defined(__XICS_H__)
+#define __XICS_H__
+
+#define XICS_IPI        0x2
+
+struct icp_state;
+
+qemu_irq xics_find_qirq(struct icp_state *icp, int irq);
+
+struct icp_state *xics_system_init(int nr_servers, CPUState *servers[],
+                                   int nr_irqs);
+
+#endif /* __XICS_H__ */
commit 821303f59b63ab832f0921f070db55e95bb21858
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:24 2011 +1100

    Implement assorted pSeries hcalls and RTAS methods
    
    This patch adds several small utility hypercalls and RTAS methods to
    the pSeries platform emulation.  Specifically:
    
    * 'display-character' rtas call
    
    This just prints a character to the console, it's occasionally used
    for early debug of the OS.  The support includes a hack to make this
    RTAS call respond on the normal token value present on real hardware,
    since some early debugging tools just assume this value without
    checking the device tree.
    
    * 'get-time-of-day' rtas call
    
    This one just takes the host real time, converts to the PAPR described
    format and returns it to the guest.
    
    * 'power-off' rtas call
    
    This one shuts down the emulated system.
    
    * H_DABR hypercall
    
    On pSeries, the DABR debug register is usually a hypervisor resource
    and virtualized through this hypercall.  If the hypercall is not
    present, Linux will under some circumstances attempt to manipulate the
    DABR directly which will fail on this emulated machine.
    
    This stub implementation is enough to stop that behaviour, although it
    doesn't actually implement the requested DABR operations as yet.
    
    Signed-off-by: Paul Mackerras <paulus at samba.org>
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index c07af19..6c64de8 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -63,7 +63,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
-    char hypertas_prop[] = "hcall-pft\0hcall-term";
+    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr";
     int i;
     char *modelname;
     int ret;
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index d8c721e..a47a97b 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -248,6 +248,13 @@ static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
+static target_ulong h_set_dabr(CPUState *env, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    /* FIXME: actually implement this */
+    return H_HARDWARE;
+}
+
 static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
@@ -317,6 +324,9 @@ static void hypercall_init(void)
     spapr_register_hypercall(H_REMOVE, h_remove);
     spapr_register_hypercall(H_PROTECT, h_protect);
 
+    /* hcall-dabr */
+    spapr_register_hypercall(H_SET_DABR, h_set_dabr);
+
     /* qemu/KVM-PPC specific hcalls */
     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 }
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 3f090f5..7226853 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -38,6 +38,58 @@
 #define TOKEN_BASE      0x2000
 #define TOKEN_MAX       0x100
 
+static void rtas_display_character(sPAPREnvironment *spapr,
+                                   uint32_t token, uint32_t nargs,
+                                   target_ulong args,
+                                   uint32_t nret, target_ulong rets)
+{
+    uint8_t c = rtas_ld(args, 0);
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, 0);
+
+    if (!sdev) {
+        rtas_st(rets, 0, -1);
+    } else {
+        vty_putchars(sdev, &c, sizeof(c));
+        rtas_st(rets, 0, 0);
+    }
+}
+
+static void rtas_get_time_of_day(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    if (nret != 8) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    qemu_get_timedate(&tm, 0);
+
+    rtas_st(rets, 0, 0); /* Success */
+    rtas_st(rets, 1, tm.tm_year + 1900);
+    rtas_st(rets, 2, tm.tm_mon + 1);
+    rtas_st(rets, 3, tm.tm_mday);
+    rtas_st(rets, 4, tm.tm_hour);
+    rtas_st(rets, 5, tm.tm_min);
+    rtas_st(rets, 6, tm.tm_sec);
+    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
+}
+
+static void rtas_power_off(sPAPREnvironment *spapr,
+                           uint32_t token, uint32_t nargs, target_ulong args,
+                           uint32_t nret, target_ulong rets)
+{
+    if (nargs != 2 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    qemu_system_shutdown_request();
+    rtas_st(rets, 0, 0);
+}
+
 static struct rtas_call {
     const char *name;
     spapr_rtas_fn fn;
@@ -59,6 +111,15 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
         }
     }
 
+    /* HACK: Some Linux early debug code uses RTAS display-character,
+     * but assumes the token value is 0xa (which it is on some real
+     * machines) without looking it up in the device tree.  This
+     * special case makes this work */
+    if (token == 0xa) {
+        rtas_display_character(spapr, 0xa, nargs, args, nret, rets);
+        return H_SUCCESS;
+    }
+
     hcall_dprintf("Unknown RTAS token 0x%x\n", token);
     rtas_st(rets, 0, -3);
     return H_PARAMETER;
@@ -129,3 +190,11 @@ int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
     }
     return 0;
 }
+
+static void register_core_rtas(void)
+{
+    spapr_rtas_register("display-character", rtas_display_character);
+    spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
+    spapr_rtas_register("power-off", rtas_power_off);
+}
+device_init(register_core_rtas);
commit 39ac8455106af1ed669b8e10223420cf1ac5b190
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:23 2011 +1100

    Implement hcall based RTAS for pSeries machines
    
    On pSeries machines, operating systems can instantiate "RTAS" (Run-Time
    Abstraction Services), a runtime component of the firmware which implements
    a number of low-level, infrequently used operations.  On logical partitions
    under a hypervisor, many of the RTAS functions require hypervisor
    privilege.  For simplicity, therefore, hypervisor systems typically
    implement the in-partition RTAS as just a tiny wrapper around a hypercall
    which actually implements the various RTAS functions.
    
    This patch implements such a hypercall based RTAS for our emulated pSeries
    machine.  A tiny in-partition "firmware" calls a new hypercall, which
    looks up available RTAS services in a table.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile b/Makefile
index 89e88b4..e0b3fea 100644
--- a/Makefile
+++ b/Makefile
@@ -213,7 +213,8 @@ pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin \
-s390-zipl.rom
+s390-zipl.rom \
+spapr-rtas.bin
 else
 BLOBS=
 endif
diff --git a/Makefile.target b/Makefile.target
index cf12691..a53d99f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -233,7 +233,7 @@ obj-ppc-y += ppc_oldworld.o
 obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
-obj-ppc-y += spapr.o spapr_hcall.o spapr_vio.o
+obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
 obj-ppc-y += spapr_vty.o
 endif
 # PowerPC 4xx boards
diff --git a/configure b/configure
index 5a5827f..7d8d890 100755
--- a/configure
+++ b/configure
@@ -2461,7 +2461,9 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
         "$softmmu" = yes ; then
   roms="optionrom"
 fi
-
+if test "$cpu" = "ppc64" ; then
+  roms="$roms spapr-rtas"
+fi
 
 echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $datadir`"
diff --git a/hw/spapr.c b/hw/spapr.c
index 57140d2..c07af19 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -40,6 +40,7 @@
 #define KERNEL_LOAD_ADDR        0x00000000
 #define INITRD_LOAD_ADDR        0x02800000
 #define FDT_MAX_SIZE            0x10000
+#define RTAS_MAX_SIZE           0x10000
 
 #define TIMEBASE_FREQ           512000000ULL
 
@@ -53,6 +54,8 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                               target_phys_addr_t initrd_base,
                               target_phys_addr_t initrd_size,
                               const char *kernel_cmdline,
+                              target_phys_addr_t rtas_addr,
+                              target_phys_addr_t rtas_size,
                               long hash_shift)
 {
     void *fdt;
@@ -195,6 +198,12 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
         exit(1);
     }
 
+    /* RTAS */
+    ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
+    }
+
     _FDT((fdt_pack(fdt)));
 
     *fdt_size = fdt_totalsize(fdt);
@@ -224,11 +233,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     void *fdt, *htab;
     int i;
     ram_addr_t ram_offset;
-    target_phys_addr_t fdt_addr;
+    target_phys_addr_t fdt_addr, rtas_addr;
     uint32_t kernel_base, initrd_base;
-    long kernel_size, initrd_size, htab_size;
+    long kernel_size, initrd_size, htab_size, rtas_size;
     long pteg_shift = 17;
     int fdt_size;
+    char *filename;
 
     spapr = qemu_malloc(sizeof(*spapr));
     cpu_ppc_hypercall = emulate_spapr_hypercall;
@@ -237,6 +247,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
      * 2GB, so that it can be processed with 32-bit code if
      * necessary */
     fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
+    /* RTAS goes just below that */
+    rtas_addr = fdt_addr - RTAS_MAX_SIZE;
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -276,6 +288,14 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         envs[i]->htab_mask = htab_size - 1;
     }
 
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
+    rtas_size = load_image_targphys(filename, rtas_addr, ram_size - rtas_addr);
+    if (rtas_size < 0) {
+        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+        exit(1);
+    }
+    qemu_free(filename);
+
     spapr->vio_bus = spapr_vio_bus_init();
 
     for (i = 0; i < MAX_SERIAL_PORTS; i++) {
@@ -323,7 +343,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     /* Prepare the device tree */
     fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
                            initrd_base, initrd_size, kernel_cmdline,
-                           pteg_shift + 7);
+                           rtas_addr, rtas_size, pteg_shift + 7);
     assert(fdt != NULL);
 
     cpu_physical_memory_write(fdt_addr, fdt, fdt_size);
diff --git a/hw/spapr.h b/hw/spapr.h
index 06cca15..0dcb83a 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -237,6 +237,18 @@ typedef struct sPAPREnvironment {
 #define H_GET_MPP               0x2D4
 #define MAX_HCALL_OPCODE        H_GET_MPP
 
+/* The hcalls above are standardized in PAPR and implemented by pHyp
+ * as well.
+ *
+ * We also need some hcalls which are specific to qemu / KVM-on-POWER.
+ * So far we just need one for H_RTAS, but in future we'll need more
+ * for extensions like virtio.  We put those into the 0xf000-0xfffc
+ * range which is reserved by PAPR for "platform-specific" hcalls.
+ */
+#define KVMPPC_HCALL_BASE       0xf000
+#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
+#define KVMPPC_HCALL_MAX        KVMPPC_H_RTAS
+
 extern sPAPREnvironment *spapr;
 
 /*#define DEBUG_SPAPR_HCALLS*/
@@ -257,4 +269,24 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
 target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
                              target_ulong *args);
 
+static inline uint32_t rtas_ld(target_ulong phys, int n)
+{
+    return ldl_phys(phys + 4*n);
+}
+
+static inline void rtas_st(target_ulong phys, int n, uint32_t val)
+{
+    stl_phys(phys + 4*n, val);
+}
+
+typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,
+                              uint32_t nargs, target_ulong args,
+                              uint32_t nret, target_ulong rets);
+void spapr_rtas_register(const char *name, spapr_rtas_fn fn);
+target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
+                             uint32_t token, uint32_t nargs, target_ulong args,
+                             uint32_t nret, target_ulong rets);
+int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
+                                 target_phys_addr_t rtas_size);
+
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 0ba1717..d8c721e 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -248,20 +248,38 @@ static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-spapr_hcall_fn hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    target_ulong rtas_r3 = args[0];
+    uint32_t token = ldl_phys(rtas_r3);
+    uint32_t nargs = ldl_phys(rtas_r3 + 4);
+    uint32_t nret = ldl_phys(rtas_r3 + 8);
+
+    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
+                           nret, rtas_r3 + 12 + 4*nargs);
+}
+
+spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE];
 
 void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
 {
-    spapr_hcall_fn old_fn;
+    spapr_hcall_fn *slot;
+
+    if (opcode <= MAX_HCALL_OPCODE) {
+        assert((opcode & 0x3) == 0);
 
-    assert(opcode <= MAX_HCALL_OPCODE);
-    assert((opcode & 0x3) == 0);
+        slot = &papr_hypercall_table[opcode / 4];
+    } else {
+        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
 
-    old_fn = hypercall_table[opcode / 4];
 
-    assert(!old_fn || (fn == old_fn));
+        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
+    }
 
-    hypercall_table[opcode / 4] = fn;
+    assert(!(*slot) || (fn == *slot));
+    *slot = fn;
 }
 
 target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
@@ -274,7 +292,14 @@ target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
 
     if ((opcode <= MAX_HCALL_OPCODE)
         && ((opcode & 0x3) == 0)) {
-        spapr_hcall_fn fn = hypercall_table[opcode / 4];
+        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
+
+        if (fn) {
+            return fn(env, spapr, opcode, args);
+        }
+    } else if ((opcode >= KVMPPC_HCALL_BASE) &&
+               (opcode <= KVMPPC_HCALL_MAX)) {
+        spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
 
         if (fn) {
             return fn(env, spapr, opcode, args);
@@ -291,5 +316,8 @@ static void hypercall_init(void)
     spapr_register_hypercall(H_ENTER, h_enter);
     spapr_register_hypercall(H_REMOVE, h_remove);
     spapr_register_hypercall(H_PROTECT, h_protect);
+
+    /* qemu/KVM-PPC specific hcalls */
+    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 }
 device_init(hypercall_init);
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
new file mode 100644
index 0000000..3f090f5
--- /dev/null
+++ b/hw/spapr_rtas.c
@@ -0,0 +1,131 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * Hypercall based emulated RTAS
+ *
+ * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "cpu.h"
+#include "sysemu.h"
+#include "qemu-char.h"
+#include "hw/qdev.h"
+#include "device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+#define TOKEN_BASE      0x2000
+#define TOKEN_MAX       0x100
+
+static struct rtas_call {
+    const char *name;
+    spapr_rtas_fn fn;
+} rtas_table[TOKEN_MAX];
+
+struct rtas_call *rtas_next = rtas_table;
+
+target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
+                             uint32_t token, uint32_t nargs, target_ulong args,
+                             uint32_t nret, target_ulong rets)
+{
+    if ((token >= TOKEN_BASE)
+        && ((token - TOKEN_BASE) < TOKEN_MAX)) {
+        struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
+
+        if (call->fn) {
+            call->fn(spapr, token, nargs, args, nret, rets);
+            return H_SUCCESS;
+        }
+    }
+
+    hcall_dprintf("Unknown RTAS token 0x%x\n", token);
+    rtas_st(rets, 0, -3);
+    return H_PARAMETER;
+}
+
+void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+{
+    assert(rtas_next < (rtas_table + TOKEN_MAX));
+
+    rtas_next->name = name;
+    rtas_next->fn = fn;
+
+    rtas_next++;
+}
+
+int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
+                                 target_phys_addr_t rtas_size)
+{
+    int ret;
+    int i;
+
+    ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-base",
+                                    rtas_addr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
+                                    rtas_addr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "rtas-size",
+                                    rtas_size);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't add rtas-size property: %s\n",
+                fdt_strerror(ret));
+        return ret;
+    }
+
+    for (i = 0; i < TOKEN_MAX; i++) {
+        struct rtas_call *call = &rtas_table[i];
+
+        if (!call->fn) {
+            continue;
+        }
+
+        ret = qemu_devtree_setprop_cell(fdt, "/rtas", call->name,
+                                        i + TOKEN_BASE);
+        if (ret < 0) {
+            fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
+                    call->name, fdt_strerror(ret));
+            return ret;
+        }
+
+    }
+    return 0;
+}
diff --git a/pc-bios/spapr-rtas.bin b/pc-bios/spapr-rtas.bin
new file mode 100755
index 0000000..fc24c8e
Binary files /dev/null and b/pc-bios/spapr-rtas.bin differ
diff --git a/pc-bios/spapr-rtas/Makefile b/pc-bios/spapr-rtas/Makefile
new file mode 100644
index 0000000..dc8b23e
--- /dev/null
+++ b/pc-bios/spapr-rtas/Makefile
@@ -0,0 +1,24 @@
+all: build-all
+# Dummy command so that make thinks it has done something
+	@true
+
+include ../../config-host.mak
+include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/pc-bios/spapr-rtas)
+
+.PHONY : all clean build-all
+
+#CFLAGS += -I$(SRC_PATH)
+#QEMU_CFLAGS = $(CFLAGS)
+
+build-all: spapr-rtas.bin
+
+%.img: %.o
+	$(call quiet-command,$(CC) -nostdlib -o $@ $<,"  Building $(TARGET_DIR)$@")
+
+%.bin: %.img
+	$(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"  Building $(TARGET_DIR)$@")
+
+clean:
+	rm -f *.o *.d *.img *.bin *~
diff --git a/pc-bios/spapr-rtas/spapr-rtas.S b/pc-bios/spapr-rtas/spapr-rtas.S
new file mode 100644
index 0000000..903bec2
--- /dev/null
+++ b/pc-bios/spapr-rtas/spapr-rtas.S
@@ -0,0 +1,37 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * Trivial in-partition RTAS implementation, based on a hypercall
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#define KVMPPC_HCALL_BASE       0xf000
+#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
+
+.globl	_start
+_start:
+	mr	4,3
+	lis	3,KVMPPC_H_RTAS at h
+	ori	3,3,KVMPPC_H_RTAS at l
+	sc	1
+	blr
commit f43e35255cffb6ac6230dd09d308f7909f823f96
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:22 2011 +1100

    Virtual hash page table handling on pSeries machine
    
    On pSeries logical partitions, excepting the old POWER4-style full system
    partitions, the guest does not have direct access to the hardware page
    table.  Instead, the pagetable exists in hypervisor memory, and the guest
    must manipulate it with hypercalls.
    
    However, our current pSeries emulation more closely resembles the old
    style where the guest must set up and handle the pagetables itself.  This
    patch converts it to act like a modern partition.
    
    This involves two things: first, the hash translation path is modified to
    permit the has table to be stored externally to the emulated machine's
    RAM.  The pSeries machine init code configures the CPUs to use this mode.
    
    Secondly, we emulate the PAPR hypercalls for manipulating the external
    hashed page table.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index c24c92b..57140d2 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -52,12 +52,15 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
                               sPAPREnvironment *spapr,
                               target_phys_addr_t initrd_base,
                               target_phys_addr_t initrd_size,
-                              const char *kernel_cmdline)
+                              const char *kernel_cmdline,
+                              long hash_shift)
 {
     void *fdt;
     uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) };
     uint32_t start_prop = cpu_to_be32(initrd_base);
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
+    uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
+    char hypertas_prop[] = "hcall-pft\0hcall-term";
     int i;
     char *modelname;
     int ret;
@@ -145,6 +148,8 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
          * full emu, for kvm we should copy it from the host */
         _FDT((fdt_property_cell(fdt, "clock-frequency", 1000000000)));
         _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
+        _FDT((fdt_property(fdt, "ibm,pft-size",
+                           pft_size_prop, sizeof(pft_size_prop))));
         _FDT((fdt_property_string(fdt, "status", "okay")));
         _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
 
@@ -160,6 +165,14 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
     _FDT((fdt_end_node(fdt)));
 
+    /* RTAS */
+    _FDT((fdt_begin_node(fdt, "rtas")));
+
+    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
+                       sizeof(hypertas_prop))));
+
+    _FDT((fdt_end_node(fdt)));
+
     /* vdevice */
     _FDT((fdt_begin_node(fdt, "vdevice")));
 
@@ -208,12 +221,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *cpu_model)
 {
     CPUState *envs[MAX_CPUS];
-    void *fdt;
+    void *fdt, *htab;
     int i;
     ram_addr_t ram_offset;
     target_phys_addr_t fdt_addr;
     uint32_t kernel_base, initrd_base;
-    long kernel_size, initrd_size;
+    long kernel_size, initrd_size, htab_size;
+    long pteg_shift = 17;
     int fdt_size;
 
     spapr = qemu_malloc(sizeof(*spapr));
@@ -250,6 +264,18 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
+    /* allocate hash page table.  For now we always make this 16mb,
+     * later we should probably make it scale to the size of guest
+     * RAM */
+    htab_size = 1ULL << (pteg_shift + 7);
+    htab = qemu_mallocz(htab_size);
+
+    for (i = 0; i < smp_cpus; i++) {
+        envs[i]->external_htab = htab;
+        envs[i]->htab_base = -1;
+        envs[i]->htab_mask = htab_size - 1;
+    }
+
     spapr->vio_bus = spapr_vio_bus_init();
 
     for (i = 0; i < MAX_SERIAL_PORTS; i++) {
@@ -296,7 +322,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     /* Prepare the device tree */
     fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
-                           initrd_base, initrd_size, kernel_cmdline);
+                           initrd_base, initrd_size, kernel_cmdline,
+                           pteg_shift + 7);
     assert(fdt != NULL);
 
     cpu_physical_memory_write(fdt_addr, fdt, fdt_size);
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index e3919d0..0ba1717 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -1,8 +1,253 @@
 #include "sysemu.h"
 #include "cpu.h"
 #include "qemu-char.h"
+#include "sysemu.h"
+#include "qemu-char.h"
+#include "exec-all.h"
 #include "hw/spapr.h"
 
+#define HPTES_PER_GROUP 8
+
+#define HPTE_V_SSIZE_SHIFT      62
+#define HPTE_V_AVPN_SHIFT       7
+#define HPTE_V_AVPN             0x3fffffffffffff80ULL
+#define HPTE_V_AVPN_VAL(x)      (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
+#define HPTE_V_COMPARE(x, y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
+#define HPTE_V_BOLTED           0x0000000000000010ULL
+#define HPTE_V_LOCK             0x0000000000000008ULL
+#define HPTE_V_LARGE            0x0000000000000004ULL
+#define HPTE_V_SECONDARY        0x0000000000000002ULL
+#define HPTE_V_VALID            0x0000000000000001ULL
+
+#define HPTE_R_PP0              0x8000000000000000ULL
+#define HPTE_R_TS               0x4000000000000000ULL
+#define HPTE_R_KEY_HI           0x3000000000000000ULL
+#define HPTE_R_RPN_SHIFT        12
+#define HPTE_R_RPN              0x3ffffffffffff000ULL
+#define HPTE_R_FLAGS            0x00000000000003ffULL
+#define HPTE_R_PP               0x0000000000000003ULL
+#define HPTE_R_N                0x0000000000000004ULL
+#define HPTE_R_G                0x0000000000000008ULL
+#define HPTE_R_M                0x0000000000000010ULL
+#define HPTE_R_I                0x0000000000000020ULL
+#define HPTE_R_W                0x0000000000000040ULL
+#define HPTE_R_WIMG             0x0000000000000078ULL
+#define HPTE_R_C                0x0000000000000080ULL
+#define HPTE_R_R                0x0000000000000100ULL
+#define HPTE_R_KEY_LO           0x0000000000000e00ULL
+
+#define HPTE_V_1TB_SEG          0x4000000000000000ULL
+#define HPTE_V_VRMA_MASK        0x4001ffffff000000ULL
+
+#define HPTE_V_HVLOCK           0x40ULL
+
+static inline int lock_hpte(void *hpte, target_ulong bits)
+{
+    uint64_t pteh;
+
+    pteh = ldq_p(hpte);
+
+    /* We're protected by qemu's global lock here */
+    if (pteh & bits) {
+        return 0;
+    }
+    stq_p(hpte, pteh | HPTE_V_HVLOCK);
+    return 1;
+}
+
+static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
+                                     target_ulong pte_index)
+{
+    target_ulong rb, va_low;
+
+    rb = (v & ~0x7fULL) << 16; /* AVA field */
+    va_low = pte_index >> 3;
+    if (v & HPTE_V_SECONDARY) {
+        va_low = ~va_low;
+    }
+    /* xor vsid from AVA */
+    if (!(v & HPTE_V_1TB_SEG)) {
+        va_low ^= v >> 12;
+    } else {
+        va_low ^= v >> 24;
+    }
+    va_low &= 0x7ff;
+    if (v & HPTE_V_LARGE) {
+        rb |= 1;                         /* L field */
+#if 0 /* Disable that P7 specific bit for now */
+        if (r & 0xff000) {
+            /* non-16MB large page, must be 64k */
+            /* (masks depend on page size) */
+            rb |= 0x1000;                /* page encoding in LP field */
+            rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+            rb |= (va_low & 0xfe);       /* AVAL field */
+        }
+#endif
+    } else {
+        /* 4kB page */
+        rb |= (va_low & 0x7ff) << 12;   /* remaining 11b of AVA */
+    }
+    rb |= (v >> 54) & 0x300;            /* B field */
+    return rb;
+}
+
+static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
+                            target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong pteh = args[2];
+    target_ulong ptel = args[3];
+    target_ulong porder;
+    target_ulong i, pa;
+    uint8_t *hpte;
+
+    /* only handle 4k and 16M pages for now */
+    porder = 12;
+    if (pteh & HPTE_V_LARGE) {
+#if 0 /* We don't support 64k pages yet */
+        if ((ptel & 0xf000) == 0x1000) {
+            /* 64k page */
+            porder = 16;
+        } else
+#endif
+        if ((ptel & 0xff000) == 0) {
+            /* 16M page */
+            porder = 24;
+            /* lowest AVA bit must be 0 for 16M pages */
+            if (pteh & 0x80) {
+                return H_PARAMETER;
+            }
+        } else {
+            return H_PARAMETER;
+        }
+    }
+
+    pa = ptel & HPTE_R_RPN;
+    /* FIXME: bounds check the pa? */
+
+    /* Check WIMG */
+    if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
+        return H_PARAMETER;
+    }
+    pteh &= ~0x60ULL;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+    if (likely((flags & H_EXACT) == 0)) {
+        pte_index &= ~7ULL;
+        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        for (i = 0; ; ++i) {
+            if (i == 8) {
+                return H_PTEG_FULL;
+            }
+            if (((ldq_p(hpte) & HPTE_V_VALID) == 0) &&
+                lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+                break;
+            }
+            hpte += HASH_PTE_SIZE_64;
+        }
+    } else {
+        i = 0;
+        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+            return H_PTEG_FULL;
+        }
+    }
+    stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
+    /* eieio();  FIXME: need some sort of barrier for smp? */
+    stq_p(hpte, pteh);
+
+    assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+    args[0] = pte_index + i;
+    return H_SUCCESS;
+}
+
+static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
+                             target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    uint8_t *hpte;
+    target_ulong v, r, rb;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+
+    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+    while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
+        /* We have no real concurrency in qemu soft-emulation, so we
+         * will never actually have a contested lock */
+        assert(0);
+    }
+
+    v = ldq_p(hpte);
+    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+
+    if ((v & HPTE_V_VALID) == 0 ||
+        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
+        ((flags & H_ANDCOND) && (v & avpn) != 0)) {
+        stq_p(hpte, v & ~HPTE_V_HVLOCK);
+        assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+        return H_NOT_FOUND;
+    }
+    args[0] = v & ~HPTE_V_HVLOCK;
+    args[1] = r;
+    stq_p(hpte, 0);
+    rb = compute_tlbie_rb(v, r, pte_index);
+    ppc_tlb_invalidate_one(env, rb);
+    assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+    return H_SUCCESS;
+}
+
+static target_ulong h_protect(CPUState *env, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    uint8_t *hpte;
+    target_ulong v, r, rb;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+
+    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+    while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
+        /* We have no real concurrency in qemu soft-emulation, so we
+         * will never actually have a contested lock */
+        assert(0);
+    }
+
+    v = ldq_p(hpte);
+    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+
+    if ((v & HPTE_V_VALID) == 0 ||
+        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
+        stq_p(hpte, v & ~HPTE_V_HVLOCK);
+        assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+        return H_NOT_FOUND;
+    }
+
+    r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
+           HPTE_R_KEY_HI | HPTE_R_KEY_LO);
+    r |= (flags << 55) & HPTE_R_PP0;
+    r |= (flags << 48) & HPTE_R_KEY_HI;
+    r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+    rb = compute_tlbie_rb(v, r, pte_index);
+    stq_p(hpte, v & ~HPTE_V_VALID);
+    ppc_tlb_invalidate_one(env, rb);
+    stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
+    /* Don't need a memory barrier, due to qemu's global lock */
+    stq_p(hpte, v & ~HPTE_V_HVLOCK);
+    assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+    return H_SUCCESS;
+}
+
 spapr_hcall_fn hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 
 void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
@@ -39,3 +284,12 @@ target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
     hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
     return H_FUNCTION;
 }
+
+static void hypercall_init(void)
+{
+    /* hcall-pft */
+    spapr_register_hypercall(H_ENTER, h_enter);
+    spapr_register_hypercall(H_REMOVE, h_remove);
+    spapr_register_hypercall(H_PROTECT, h_protect);
+}
+device_init(hypercall_init);
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 25d0658..b4c2555 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -670,6 +670,8 @@ struct CPUPPCState {
     target_phys_addr_t htab_base;
     target_phys_addr_t htab_mask;
     target_ulong sr[32];
+    /* externally stored hash table */
+    uint8_t *external_htab;
     /* BATs */
     int nb_BATs;
     target_ulong DBAT[2][8];
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 278bee4..5e4030b 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -589,8 +589,13 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
     for (i = 0; i < 8; i++) {
 #if defined(TARGET_PPC64)
         if (is_64b) {
-            pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
-            pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
+            if (env->external_htab) {
+                pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
+                pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
+            } else {
+                pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
+                pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
+            }
 
             /* We have a TLB that saves 4K pages, so let's
              * split a huge page to 4k chunks */
@@ -606,8 +611,13 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
         } else
 #endif
         {
-            pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
-            pte1 =  ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
+            if (env->external_htab) {
+                pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
+                pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
+            } else {
+                pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
+                pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
+            }
             r = pte32_check(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
                     TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
@@ -647,13 +657,23 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
         if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
 #if defined(TARGET_PPC64)
             if (is_64b) {
-                stq_phys_notdirty(env->htab_base + pteg_off + (good * 16) + 8,
-                                  pte1);
+                if (env->external_htab) {
+                    stq_p(env->external_htab + pteg_off + (good * 16) + 8,
+                          pte1);
+                } else {
+                    stq_phys_notdirty(env->htab_base + pteg_off +
+                                      (good * 16) + 8, pte1);
+                }
             } else
 #endif
             {
-                stl_phys_notdirty(env->htab_base + pteg_off + (good * 8) + 4,
-                                  pte1);
+                if (env->external_htab) {
+                    stl_p(env->external_htab + pteg_off + (good * 8) + 4,
+                          pte1);
+                } else {
+                    stl_phys_notdirty(env->htab_base + pteg_off +
+                                      (good * 8) + 4, pte1);
+                }
             }
         }
     }
commit 4040ab72379f75fe171c03f93ceb75efb48c14a5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:21 2011 +1100

    Implement the bus structure for PAPR virtual IO
    
    This extends the "pseries" (PAPR) machine to include a virtual IO bus
    supporting the PAPR defined hypercall based virtual IO mechanisms.
    
    So far only one VIO device is provided, the vty / vterm, providing
    a full console (polled only, for now).
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index ccf090b..cf12691 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -231,9 +231,10 @@ obj-ppc-y += ppc_prep.o
 obj-ppc-y += ppc_oldworld.o
 # NewWorld PowerMac
 obj-ppc-y += ppc_newworld.o
-# IBM pSeries (sPAPR)i
+# IBM pSeries (sPAPR)
 ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
-obj-ppc-y += spapr.o spapr_hcall.o
+obj-ppc-y += spapr.o spapr_hcall.o spapr_vio.o
+obj-ppc-y += spapr_vty.o
 endif
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
diff --git a/hw/spapr.c b/hw/spapr.c
index 410213a..c24c92b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -25,7 +25,6 @@
  *
  */
 #include "sysemu.h"
-#include "qemu-char.h"
 #include "hw.h"
 #include "elf.h"
 
@@ -34,6 +33,7 @@
 #include "hw/loader.h"
 
 #include "hw/spapr.h"
+#include "hw/spapr_vio.h"
 
 #include <libfdt.h>
 
@@ -60,6 +60,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     int i;
     char *modelname;
+    int ret;
 
 #define _FDT(exp) \
     do { \
@@ -159,9 +160,30 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
 
     _FDT((fdt_end_node(fdt)));
 
+    /* vdevice */
+    _FDT((fdt_begin_node(fdt, "vdevice")));
+
+    _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
+    _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+
+    _FDT((fdt_end_node(fdt)));
+
     _FDT((fdt_end_node(fdt))); /* close root node */
     _FDT((fdt_finish(fdt)));
 
+    /* re-expand to allow for further tweaks */
+    _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
+
+    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup vio devices in fdt\n");
+        exit(1);
+    }
+
+    _FDT((fdt_pack(fdt)));
+
     *fdt_size = fdt_totalsize(fdt);
 
     return fdt;
@@ -177,21 +199,6 @@ static void emulate_spapr_hypercall(CPUState *env)
     env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
 }
 
-/* FIXME: hack until we implement the proper VIO console */
-static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
-                                    target_ulong opcode, target_ulong *args)
-{
-    uint8_t buf[16];
-
-    stq_p(buf, args[2]);
-    stq_p(buf + 8, args[3]);
-
-    qemu_chr_write(serial_hds[0], buf, args[1]);
-
-    return 0;
-}
-
-
 /* pSeries LPAR / sPAPR hardware init */
 static void ppc_spapr_init(ram_addr_t ram_size,
                            const char *boot_device,
@@ -243,7 +250,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
-    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
+    spapr->vio_bus = spapr_vio_bus_init();
+
+    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            spapr_vty_create(spapr->vio_bus, i, serial_hds[i]);
+        }
+    }
 
     if (kernel_filename) {
         uint64_t lowaddr = 0;
@@ -276,7 +289,6 @@ static void ppc_spapr_init(ram_addr_t ram_size,
             initrd_base = 0;
             initrd_size = 0;
         }
-
     } else {
         fprintf(stderr, "pSeries machine needs -kernel for now");
         exit(1);
diff --git a/hw/spapr.h b/hw/spapr.h
index 685944b..06cca15 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -1,7 +1,10 @@
 #if !defined(__HW_SPAPR_H__)
 #define __HW_SPAPR_H__
 
+struct VIOsPAPRBus;
+
 typedef struct sPAPREnvironment {
+    struct VIOsPAPRBus *vio_bus;
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
new file mode 100644
index 0000000..10acb4c
--- /dev/null
+++ b/hw/spapr_vio.c
@@ -0,0 +1,214 @@
+/*
+ * QEMU sPAPR VIO code
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <dwg at au1.ibm.com>
+ * Based on the s390 virtio bus code:
+ * Copyright (c) 2009 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "monitor.h"
+#include "loader.h"
+#include "elf.h"
+#include "hw/sysbus.h"
+#include "kvm.h"
+#include "device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#ifdef CONFIG_FDT
+#include <libfdt.h>
+#endif /* CONFIG_FDT */
+
+/* #define DEBUG_SPAPR */
+
+#ifdef DEBUG_SPAPR
+#define dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+static struct BusInfo spapr_vio_bus_info = {
+    .name       = "spapr-vio",
+    .size       = sizeof(VIOsPAPRBus),
+};
+
+VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
+{
+    DeviceState *qdev;
+    VIOsPAPRDevice *dev = NULL;
+
+    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)qdev;
+        if (dev->reg == reg) {
+            break;
+        }
+    }
+
+    return dev;
+}
+
+#ifdef CONFIG_FDT
+static int vio_make_devnode(VIOsPAPRDevice *dev,
+                            void *fdt)
+{
+    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+    int vdevice_off, node_off;
+    int ret;
+
+    vdevice_off = fdt_path_offset(fdt, "/vdevice");
+    if (vdevice_off < 0) {
+        return vdevice_off;
+    }
+
+    node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id);
+    if (node_off < 0) {
+        return node_off;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (info->dt_type) {
+        ret = fdt_setprop_string(fdt, node_off, "device_type",
+                                 info->dt_type);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (info->dt_compatible) {
+        ret = fdt_setprop_string(fdt, node_off, "compatible",
+                                 info->dt_compatible);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (info->devnode) {
+        ret = (info->devnode)(dev, fdt, node_off);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return node_off;
+}
+#endif /* CONFIG_FDT */
+
+static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
+{
+    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
+    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+    char *id;
+
+    if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) {
+        return -1;
+    }
+
+    dev->qdev.id = id;
+
+    return info->init(dev);
+}
+
+void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info)
+{
+    info->qdev.init = spapr_vio_busdev_init;
+    info->qdev.bus_info = &spapr_vio_bus_info;
+
+    assert(info->qdev.size >= sizeof(VIOsPAPRDevice));
+    qdev_register(&info->qdev);
+}
+
+VIOsPAPRBus *spapr_vio_bus_init(void)
+{
+    VIOsPAPRBus *bus;
+    BusState *qbus;
+    DeviceState *dev;
+    DeviceInfo *qinfo;
+
+    /* Create bridge device */
+    dev = qdev_create(NULL, "spapr-vio-bridge");
+    qdev_init_nofail(dev);
+
+    /* Create bus on bridge device */
+
+    qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
+    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
+
+    for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
+        VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
+
+        if (qinfo->bus_info != &spapr_vio_bus_info) {
+            continue;
+        }
+
+        if (info->hcalls) {
+            info->hcalls(bus);
+        }
+    }
+
+    return bus;
+}
+
+/* Represents sPAPR hcall VIO devices */
+
+static int spapr_vio_bridge_init(SysBusDevice *dev)
+{
+    /* nothing */
+    return 0;
+}
+
+static SysBusDeviceInfo spapr_vio_bridge_info = {
+    .init = spapr_vio_bridge_init,
+    .qdev.name  = "spapr-vio-bridge",
+    .qdev.size  = sizeof(SysBusDevice),
+    .qdev.no_user = 1,
+};
+
+static void spapr_vio_register_devices(void)
+{
+    sysbus_register_withprop(&spapr_vio_bridge_info);
+}
+
+device_init(spapr_vio_register_devices)
+
+#ifdef CONFIG_FDT
+int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
+{
+    DeviceState *qdev;
+    int ret = 0;
+
+    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
+        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+
+        ret = vio_make_devnode(dev, fdt);
+
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+#endif /* CONFIG_FDT */
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
new file mode 100644
index 0000000..b164ad3
--- /dev/null
+++ b/hw/spapr_vio.h
@@ -0,0 +1,50 @@
+#ifndef _HW_SPAPR_VIO_H
+#define _HW_SPAPR_VIO_H
+/*
+ * QEMU sPAPR VIO bus definitions
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <david at gibson.dropbear.id.au>
+ * Based on the s390 virtio bus definitions:
+ * Copyright (c) 2009 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+typedef struct VIOsPAPRDevice {
+    DeviceState qdev;
+    uint32_t reg;
+} VIOsPAPRDevice;
+
+typedef struct VIOsPAPRBus {
+    BusState bus;
+} VIOsPAPRBus;
+
+typedef struct {
+    DeviceInfo qdev;
+    const char *dt_name, *dt_type, *dt_compatible;
+    int (*init)(VIOsPAPRDevice *dev);
+    void (*hcalls)(VIOsPAPRBus *bus);
+    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
+} VIOsPAPRDeviceInfo;
+
+extern VIOsPAPRBus *spapr_vio_bus_init(void);
+extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
+extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
+extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
+
+void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
+void spapr_vty_create(VIOsPAPRBus *bus,
+                      uint32_t reg, CharDriverState *chardev);
+
+#endif /* _HW_SPAPR_VIO_H */
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
new file mode 100644
index 0000000..b4da6a8
--- /dev/null
+++ b/hw/spapr_vty.c
@@ -0,0 +1,150 @@
+#include "qdev.h"
+#include "qemu-char.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#define VTERM_BUFSIZE   16
+
+typedef struct VIOsPAPRVTYDevice {
+    VIOsPAPRDevice sdev;
+    CharDriverState *chardev;
+    uint32_t in, out;
+    uint8_t buf[VTERM_BUFSIZE];
+} VIOsPAPRVTYDevice;
+
+static int vty_can_receive(void *opaque)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+
+    return (dev->in - dev->out) < VTERM_BUFSIZE;
+}
+
+static void vty_receive(void *opaque, const uint8_t *buf, int size)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        assert((dev->in - dev->out) < VTERM_BUFSIZE);
+        dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
+    }
+}
+
+static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+    int n = 0;
+
+    while ((n < max) && (dev->out != dev->in)) {
+        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
+    }
+
+    return n;
+}
+
+void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+
+    /* FIXME: should check the qemu_chr_write() return value */
+    qemu_chr_write(dev->chardev, buf, len);
+}
+
+static int spapr_vty_init(VIOsPAPRDevice *sdev)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+
+    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+                          vty_receive, NULL, dev);
+
+    return 0;
+}
+
+static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong len = args[1];
+    target_ulong char0_7 = args[2];
+    target_ulong char8_15 = args[3];
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    uint8_t buf[16];
+
+    if (!sdev) {
+        return H_PARAMETER;
+    }
+
+    if (len > 16) {
+        return H_PARAMETER;
+    }
+
+    *((uint64_t *)buf) = cpu_to_be64(char0_7);
+    *((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
+
+    vty_putchars(sdev, buf, len);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong reg = args[0];
+    target_ulong *len = args + 0;
+    target_ulong *char0_7 = args + 1;
+    target_ulong *char8_15 = args + 2;
+    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    uint8_t buf[16];
+
+    if (!sdev) {
+        return H_PARAMETER;
+    }
+
+    *len = vty_getchars(sdev, buf, sizeof(buf));
+    if (*len < 16) {
+        memset(buf + *len, 0, 16 - *len);
+    }
+
+    *char0_7 = be64_to_cpu(*((uint64_t *)buf));
+    *char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
+
+    return H_SUCCESS;
+}
+
+void spapr_vty_create(VIOsPAPRBus *bus,
+                      uint32_t reg, CharDriverState *chardev)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(&bus->bus, "spapr-vty");
+    qdev_prop_set_uint32(dev, "reg", reg);
+    qdev_prop_set_chr(dev, "chardev", chardev);
+    qdev_init_nofail(dev);
+}
+
+static void vty_hcalls(VIOsPAPRBus *bus)
+{
+    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
+    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
+}
+
+static VIOsPAPRDeviceInfo spapr_vty = {
+    .init = spapr_vty_init,
+    .dt_name = "vty",
+    .dt_type = "serial",
+    .dt_compatible = "hvterm1",
+    .hcalls = vty_hcalls,
+    .qdev.name = "spapr-vty",
+    .qdev.size = sizeof(VIOsPAPRVTYDevice),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0),
+        DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void spapr_vty_register(void)
+{
+    spapr_vio_bus_register_withprop(&spapr_vty);
+}
+device_init(spapr_vty_register);
commit 9fdf0c2995d04a74a22ea4609b2931eef209e53d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:20 2011 +1100

    Start implementing pSeries logical partition machine
    
    This patch adds a "pseries" machine to qemu.  This aims to emulate a
    logical partition on an IBM pSeries machine, compliant to the
    "PowerPC Architecture Platform Requirements" (PAPR) document.
    
    This initial version is quite limited, it implements a basic machine
    and PAPR hypercall emulation.  So far only one hypercall is present -
    H_PUT_TERM_CHAR - so that a (write-only) console is available.
    
    Multiple CPUs are permitted, with SMP entry handled kexec() style.
    
    The machine so far more resembles an old POWER4 style "full system
    partition" rather than a modern LPAR, in that the guest manages the
    page tables directly, rather than via hypercalls.
    
    The machine requires qemu to be configured with --enable-fdt.  The
    machine can (so far) only be booted with -kernel - i.e. no partition
    firmware is provided.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index 62b102a..ccf090b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -231,6 +231,10 @@ obj-ppc-y += ppc_prep.o
 obj-ppc-y += ppc_oldworld.o
 # NewWorld PowerMac
 obj-ppc-y += ppc_newworld.o
+# IBM pSeries (sPAPR)i
+ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
+obj-ppc-y += spapr.o spapr_hcall.o
+endif
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-ppc-y += ppc440.o ppc440_bamboo.o
diff --git a/hw/spapr.c b/hw/spapr.c
new file mode 100644
index 0000000..410213a
--- /dev/null
+++ b/hw/spapr.c
@@ -0,0 +1,313 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2010 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "sysemu.h"
+#include "qemu-char.h"
+#include "hw.h"
+#include "elf.h"
+
+#include "hw/boards.h"
+#include "hw/ppc.h"
+#include "hw/loader.h"
+
+#include "hw/spapr.h"
+
+#include <libfdt.h>
+
+#define KERNEL_LOAD_ADDR        0x00000000
+#define INITRD_LOAD_ADDR        0x02800000
+#define FDT_MAX_SIZE            0x10000
+
+#define TIMEBASE_FREQ           512000000ULL
+
+#define MAX_CPUS                32
+
+sPAPREnvironment *spapr;
+
+static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
+                              const char *cpu_model, CPUState *envs[],
+                              sPAPREnvironment *spapr,
+                              target_phys_addr_t initrd_base,
+                              target_phys_addr_t initrd_size,
+                              const char *kernel_cmdline)
+{
+    void *fdt;
+    uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) };
+    uint32_t start_prop = cpu_to_be32(initrd_base);
+    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
+    int i;
+    char *modelname;
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+                    #exp, fdt_strerror(ret));                      \
+            exit(1);                                               \
+        }                                                          \
+    } while (0)
+
+    fdt = qemu_mallocz(FDT_MAX_SIZE);
+    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+
+    _FDT((fdt_finish_reservemap(fdt)));
+
+    /* Root node */
+    _FDT((fdt_begin_node(fdt, "")));
+    _FDT((fdt_property_string(fdt, "device_type", "chrp")));
+    _FDT((fdt_property_string(fdt, "model", "qemu,emulated-pSeries-LPAR")));
+
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
+
+    /* /chosen */
+    _FDT((fdt_begin_node(fdt, "chosen")));
+
+    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
+    _FDT((fdt_property(fdt, "linux,initrd-start",
+                       &start_prop, sizeof(start_prop))));
+    _FDT((fdt_property(fdt, "linux,initrd-end",
+                       &end_prop, sizeof(end_prop))));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* memory node */
+    _FDT((fdt_begin_node(fdt, "memory at 0")));
+
+    _FDT((fdt_property_string(fdt, "device_type", "memory")));
+    _FDT((fdt_property(fdt, "reg",
+                       mem_reg_property, sizeof(mem_reg_property))));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* cpus */
+    _FDT((fdt_begin_node(fdt, "cpus")));
+
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+
+    modelname = qemu_strdup(cpu_model);
+
+    for (i = 0; i < strlen(modelname); i++) {
+        modelname[i] = toupper(modelname[i]);
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        CPUState *env = envs[i];
+        char *nodename;
+        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
+                           0xffffffff, 0xffffffff};
+
+        if (asprintf(&nodename, "%s@%x", modelname, i) < 0) {
+            fprintf(stderr, "Allocation failure\n");
+            exit(1);
+        }
+
+        _FDT((fdt_begin_node(fdt, nodename)));
+
+        free(nodename);
+
+        _FDT((fdt_property_cell(fdt, "reg", i)));
+        _FDT((fdt_property_string(fdt, "device_type", "cpu")));
+
+        _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
+        _FDT((fdt_property_cell(fdt, "dcache-block-size",
+                                env->dcache_line_size)));
+        _FDT((fdt_property_cell(fdt, "icache-block-size",
+                                env->icache_line_size)));
+        _FDT((fdt_property_cell(fdt, "timebase-frequency", TIMEBASE_FREQ)));
+        /* Hardcode CPU frequency for now.  It's kind of arbitrary on
+         * full emu, for kvm we should copy it from the host */
+        _FDT((fdt_property_cell(fdt, "clock-frequency", 1000000000)));
+        _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
+        _FDT((fdt_property_string(fdt, "status", "okay")));
+        _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
+
+        if (envs[i]->mmu_model & POWERPC_MMU_1TSEG) {
+            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
+                               segs, sizeof(segs))));
+        }
+
+        _FDT((fdt_end_node(fdt)));
+    }
+
+    qemu_free(modelname);
+
+    _FDT((fdt_end_node(fdt)));
+
+    _FDT((fdt_end_node(fdt))); /* close root node */
+    _FDT((fdt_finish(fdt)));
+
+    *fdt_size = fdt_totalsize(fdt);
+
+    return fdt;
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
+static void emulate_spapr_hypercall(CPUState *env)
+{
+    env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
+}
+
+/* FIXME: hack until we implement the proper VIO console */
+static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    uint8_t buf[16];
+
+    stq_p(buf, args[2]);
+    stq_p(buf + 8, args[3]);
+
+    qemu_chr_write(serial_hds[0], buf, args[1]);
+
+    return 0;
+}
+
+
+/* pSeries LPAR / sPAPR hardware init */
+static void ppc_spapr_init(ram_addr_t ram_size,
+                           const char *boot_device,
+                           const char *kernel_filename,
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           const char *cpu_model)
+{
+    CPUState *envs[MAX_CPUS];
+    void *fdt;
+    int i;
+    ram_addr_t ram_offset;
+    target_phys_addr_t fdt_addr;
+    uint32_t kernel_base, initrd_base;
+    long kernel_size, initrd_size;
+    int fdt_size;
+
+    spapr = qemu_malloc(sizeof(*spapr));
+    cpu_ppc_hypercall = emulate_spapr_hypercall;
+
+    /* We place the device tree just below either the top of RAM, or
+     * 2GB, so that it can be processed with 32-bit code if
+     * necessary */
+    fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "POWER7";
+    }
+    for (i = 0; i < smp_cpus; i++) {
+        CPUState *env = cpu_init(cpu_model);
+
+        if (!env) {
+            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+            exit(1);
+        }
+        /* Set time-base frequency to 512 MHz */
+        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
+        qemu_register_reset((QEMUResetHandler *)&cpu_reset, env);
+
+        env->hreset_vector = 0x60;
+        env->hreset_excp_prefix = 0;
+        env->gpr[3] = i;
+
+        envs[i] = env;
+    }
+
+    /* allocate RAM */
+    ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_offset);
+
+    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
+
+    if (kernel_filename) {
+        uint64_t lowaddr = 0;
+
+        kernel_base = KERNEL_LOAD_ADDR;
+
+        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, kernel_base,
+                                              ram_size - kernel_base);
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              ram_size - initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+
+    } else {
+        fprintf(stderr, "pSeries machine needs -kernel for now");
+        exit(1);
+    }
+
+    /* Prepare the device tree */
+    fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
+                           initrd_base, initrd_size, kernel_cmdline);
+    assert(fdt != NULL);
+
+    cpu_physical_memory_write(fdt_addr, fdt, fdt_size);
+
+    qemu_free(fdt);
+
+    envs[0]->gpr[3] = fdt_addr;
+    envs[0]->gpr[5] = 0;
+    envs[0]->hreset_vector = kernel_base;
+}
+
+static QEMUMachine spapr_machine = {
+    .name = "pseries",
+    .desc = "pSeries Logical Partition (PAPR compliant)",
+    .init = ppc_spapr_init,
+    .max_cpus = MAX_CPUS,
+    .no_vga = 1,
+    .no_parallel = 1,
+};
+
+static void spapr_machine_init(void)
+{
+    qemu_register_machine(&spapr_machine);
+}
+
+machine_init(spapr_machine_init);
diff --git a/hw/spapr.h b/hw/spapr.h
new file mode 100644
index 0000000..685944b
--- /dev/null
+++ b/hw/spapr.h
@@ -0,0 +1,257 @@
+#if !defined(__HW_SPAPR_H__)
+#define __HW_SPAPR_H__
+
+typedef struct sPAPREnvironment {
+} sPAPREnvironment;
+
+#define H_SUCCESS         0
+#define H_BUSY            1        /* Hardware busy -- retry later */
+#define H_CLOSED          2        /* Resource closed */
+#define H_NOT_AVAILABLE   3
+#define H_CONSTRAINED     4        /* Resource request constrained to max allowed */
+#define H_PARTIAL         5
+#define H_IN_PROGRESS     14       /* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE   16
+#define H_PENDING         17       /* returned from H_POLL_PENDING */
+#define H_CONTINUE        18       /* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE         9900  /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC        9900  /* Long busy, hint that 1msec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC       9901  /* Long busy, hint that 10msec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC      9902  /* Long busy, hint that 100msec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC         9903  /* Long busy, hint that 1sec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC        9904  /* Long busy, hint that 10sec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC       9905  /* Long busy, hint that 100sec \
+                                                 is a good time to retry */
+#define H_LONG_BUSY_END_RANGE           9905  /* End of long busy range */
+#define H_HARDWARE        -1       /* Hardware error */
+#define H_FUNCTION        -2       /* Function not supported */
+#define H_PRIVILEGE       -3       /* Caller not privileged */
+#define H_PARAMETER       -4       /* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE        -5       /* Illegal msr value */
+#define H_PTEG_FULL       -6       /* PTEG is full */
+#define H_NOT_FOUND       -7       /* PTE was not found" */
+#define H_RESERVED_DABR   -8       /* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM          -9
+#define H_AUTHORITY       -10
+#define H_PERMISSION      -11
+#define H_DROPPED         -12
+#define H_SOURCE_PARM     -13
+#define H_DEST_PARM       -14
+#define H_REMOTE_PARM     -15
+#define H_RESOURCE        -16
+#define H_ADAPTER_PARM    -17
+#define H_RH_PARM         -18
+#define H_RCQ_PARM        -19
+#define H_SCQ_PARM        -20
+#define H_EQ_PARM         -21
+#define H_RT_PARM         -22
+#define H_ST_PARM         -23
+#define H_SIGT_PARM       -24
+#define H_TOKEN_PARM      -25
+#define H_MLENGTH_PARM    -27
+#define H_MEM_PARM        -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM       -30
+#define H_PORT_PARM       -31
+#define H_MCG_PARM        -32
+#define H_VL_PARM         -33
+#define H_TSIZE_PARM      -34
+#define H_TRACE_PARM      -35
+
+#define H_MASK_PARM       -37
+#define H_MCG_FULL        -38
+#define H_ALIAS_EXIST     -39
+#define H_P_COUNTER       -40
+#define H_TABLE_FULL      -41
+#define H_ALT_TABLE       -42
+#define H_MR_CONDITION    -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE         -45
+#define H_RESCINDEND      -46
+#define H_MULTI_THREADS_ACTIVE -9005
+
+
+/* Long Busy is a condition that can be returned by the firmware
+ * when a call cannot be completed now, but the identical call
+ * should be retried later.  This prevents calls blocking in the
+ * firmware for long periods of time.  Annoyingly the firmware can return
+ * a range of return codes, hinting at how long we should wait before
+ * retrying.  If you don't care for the hint, the macro below is a good
+ * way to check for the long_busy return codes
+ */
+#define H_IS_LONG_BUSY(x)  ((x >= H_LONG_BUSY_START_RANGE) \
+                            && (x <= H_LONG_BUSY_END_RANGE))
+
+/* Flags */
+#define H_LARGE_PAGE      (1ULL<<(63-16))
+#define H_EXACT           (1ULL<<(63-24))       /* Use exact PTE or return H_PTEG_FULL */
+#define H_R_XLATE         (1ULL<<(63-25))       /* include a valid logical page num in the pte if the valid bit is set */
+#define H_READ_4          (1ULL<<(63-26))       /* Return 4 PTEs */
+#define H_PAGE_STATE_CHANGE (1ULL<<(63-28))
+#define H_PAGE_UNUSED     ((1ULL<<(63-29)) | (1ULL<<(63-30)))
+#define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
+#define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1ULL<<(63-31)))
+#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE
+#define H_AVPN            (1ULL<<(63-32))       /* An avpn is provided as a sanity test */
+#define H_ANDCOND         (1ULL<<(63-33))
+#define H_ICACHE_INVALIDATE (1ULL<<(63-40))     /* icbi, etc.  (ignored for IO pages) */
+#define H_ICACHE_SYNCHRONIZE (1ULL<<(63-41))    /* dcbst, icbi, etc (ignored for IO pages */
+#define H_ZERO_PAGE       (1ULL<<(63-48))       /* zero the page before mapping (ignored for IO pages) */
+#define H_COPY_PAGE       (1ULL<<(63-49))
+#define H_N               (1ULL<<(63-61))
+#define H_PP1             (1ULL<<(63-62))
+#define H_PP2             (1ULL<<(63-63))
+
+/* VASI States */
+#define H_VASI_INVALID    0
+#define H_VASI_ENABLED    1
+#define H_VASI_ABORTED    2
+#define H_VASI_SUSPENDING 3
+#define H_VASI_SUSPENDED  4
+#define H_VASI_RESUMED    5
+#define H_VASI_COMPLETED  6
+
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR (1ULL<<(63-61))
+#define H_DABRX_KERNEL     (1ULL<<(63-62))
+#define H_DABRX_USER       (1ULL<<(63-63))
+
+/* Each control block has to be on a 4K bondary */
+#define H_CB_ALIGNMENT     4096
+
+/* pSeries hypervisor opcodes */
+#define H_REMOVE                0x04
+#define H_ENTER                 0x08
+#define H_READ                  0x0c
+#define H_CLEAR_MOD             0x10
+#define H_CLEAR_REF             0x14
+#define H_PROTECT               0x18
+#define H_GET_TCE               0x1c
+#define H_PUT_TCE               0x20
+#define H_SET_SPRG0             0x24
+#define H_SET_DABR              0x28
+#define H_PAGE_INIT             0x2c
+#define H_SET_ASR               0x30
+#define H_ASR_ON                0x34
+#define H_ASR_OFF               0x38
+#define H_LOGICAL_CI_LOAD       0x3c
+#define H_LOGICAL_CI_STORE      0x40
+#define H_LOGICAL_CACHE_LOAD    0x44
+#define H_LOGICAL_CACHE_STORE   0x48
+#define H_LOGICAL_ICBI          0x4c
+#define H_LOGICAL_DCBF          0x50
+#define H_GET_TERM_CHAR         0x54
+#define H_PUT_TERM_CHAR         0x58
+#define H_REAL_TO_LOGICAL       0x5c
+#define H_HYPERVISOR_DATA       0x60
+#define H_EOI                   0x64
+#define H_CPPR                  0x68
+#define H_IPI                   0x6c
+#define H_IPOLL                 0x70
+#define H_XIRR                  0x74
+#define H_PERFMON               0x7c
+#define H_MIGRATE_DMA           0x78
+#define H_REGISTER_VPA          0xDC
+#define H_CEDE                  0xE0
+#define H_CONFER                0xE4
+#define H_PROD                  0xE8
+#define H_GET_PPP               0xEC
+#define H_SET_PPP               0xF0
+#define H_PURR                  0xF4
+#define H_PIC                   0xF8
+#define H_REG_CRQ               0xFC
+#define H_FREE_CRQ              0x100
+#define H_VIO_SIGNAL            0x104
+#define H_SEND_CRQ              0x108
+#define H_COPY_RDMA             0x110
+#define H_REGISTER_LOGICAL_LAN  0x114
+#define H_FREE_LOGICAL_LAN      0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
+#define H_SEND_LOGICAL_LAN      0x120
+#define H_BULK_REMOVE           0x124
+#define H_MULTICAST_CTRL        0x130
+#define H_SET_XDABR             0x134
+#define H_STUFF_TCE             0x138
+#define H_PUT_TCE_INDIRECT      0x13C
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+#define H_VTERM_PARTNER_INFO    0x150
+#define H_REGISTER_VTERM        0x154
+#define H_FREE_VTERM            0x158
+#define H_RESET_EVENTS          0x15C
+#define H_ALLOC_RESOURCE        0x160
+#define H_FREE_RESOURCE         0x164
+#define H_MODIFY_QP             0x168
+#define H_QUERY_QP              0x16C
+#define H_REREGISTER_PMR        0x170
+#define H_REGISTER_SMR          0x174
+#define H_QUERY_MR              0x178
+#define H_QUERY_MW              0x17C
+#define H_QUERY_HCA             0x180
+#define H_QUERY_PORT            0x184
+#define H_MODIFY_PORT           0x188
+#define H_DEFINE_AQP1           0x18C
+#define H_GET_TRACE_BUFFER      0x190
+#define H_DEFINE_AQP0           0x194
+#define H_RESIZE_MR             0x198
+#define H_ATTACH_MCQP           0x19C
+#define H_DETACH_MCQP           0x1A0
+#define H_CREATE_RPT            0x1A4
+#define H_REMOVE_RPT            0x1A8
+#define H_REGISTER_RPAGES       0x1AC
+#define H_DISABLE_AND_GETC      0x1B0
+#define H_ERROR_DATA            0x1B4
+#define H_GET_HCA_INFO          0x1B8
+#define H_GET_PERF_COUNT        0x1BC
+#define H_MANAGE_TRACE          0x1C0
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
+#define H_QUERY_INT_STATE       0x1E4
+#define H_POLL_PENDING          0x1D8
+#define H_ILLAN_ATTRIBUTES      0x244
+#define H_MODIFY_HEA_QP         0x250
+#define H_QUERY_HEA_QP          0x254
+#define H_QUERY_HEA             0x258
+#define H_QUERY_HEA_PORT        0x25C
+#define H_MODIFY_HEA_PORT       0x260
+#define H_REG_BCMC              0x264
+#define H_DEREG_BCMC            0x268
+#define H_REGISTER_HEA_RPAGES   0x26C
+#define H_DISABLE_AND_GET_HEA   0x270
+#define H_GET_HEA_INFO          0x274
+#define H_ALLOC_HEA_RESOURCE    0x278
+#define H_ADD_CONN              0x284
+#define H_DEL_CONN              0x288
+#define H_JOIN                  0x298
+#define H_VASI_STATE            0x2A4
+#define H_ENABLE_CRQ            0x2B0
+#define H_GET_EM_PARMS          0x2B8
+#define H_SET_MPP               0x2D0
+#define H_GET_MPP               0x2D4
+#define MAX_HCALL_OPCODE        H_GET_MPP
+
+extern sPAPREnvironment *spapr;
+
+/*#define DEBUG_SPAPR_HCALLS*/
+
+#ifdef DEBUG_SPAPR_HCALLS
+#define hcall_dprintf(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define hcall_dprintf(fmt, ...) \
+    do { } while (0)
+#endif
+
+typedef target_ulong (*spapr_hcall_fn)(CPUState *env, sPAPREnvironment *spapr,
+                                       target_ulong opcode,
+                                       target_ulong *args);
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
+target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
+                             target_ulong *args);
+
+#endif /* !defined (__HW_SPAPR_H__) */
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
new file mode 100644
index 0000000..e3919d0
--- /dev/null
+++ b/hw/spapr_hcall.c
@@ -0,0 +1,41 @@
+#include "sysemu.h"
+#include "cpu.h"
+#include "qemu-char.h"
+#include "hw/spapr.h"
+
+spapr_hcall_fn hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
+{
+    spapr_hcall_fn old_fn;
+
+    assert(opcode <= MAX_HCALL_OPCODE);
+    assert((opcode & 0x3) == 0);
+
+    old_fn = hypercall_table[opcode / 4];
+
+    assert(!old_fn || (fn == old_fn));
+
+    hypercall_table[opcode / 4] = fn;
+}
+
+target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
+                             target_ulong *args)
+{
+    if (msr_pr) {
+        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
+        return H_PRIVILEGE;
+    }
+
+    if ((opcode <= MAX_HCALL_OPCODE)
+        && ((opcode & 0x3) == 0)) {
+        spapr_hcall_fn fn = hypercall_table[opcode / 4];
+
+        if (fn) {
+            return fn(env, spapr, opcode, args);
+        }
+    }
+
+    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
+    return H_FUNCTION;
+}
commit 9d52e9079da4f28abd788faf39e64fbf4b305561
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:19 2011 +1100

    Add POWER7 support for ppc
    
    This adds emulation support for the recent POWER7 cpu to qemu.  It's far
    from perfect - it's missing a number of POWER7 features so far, including
    any support for VSX or decimal floating point instructions.  However, it's
    close enough to boot a kernel with the POWER7 PVR.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc.c b/hw/ppc.c
index b55a848..dabb816 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -247,6 +247,41 @@ void ppc970_irq_init (CPUState *env)
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
                                                   PPC970_INPUT_NB);
 }
+
+/* POWER7 internal IRQ controller */
+static void power7_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    cur_level = (env->irq_input_state >> pin) & 1;
+
+    switch (pin) {
+    case POWER7_INPUT_INT:
+        /* Level sensitive - active high */
+        LOG_IRQ("%s: set the external IRQ state to %d\n",
+                __func__, level);
+        ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+        break;
+    default:
+        /* Unknown pin - do nothing */
+        LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+        return;
+    }
+    if (level) {
+        env->irq_input_state |= 1 << pin;
+    } else {
+        env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppcPOWER7_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
+                                                  POWER7_INPUT_NB);
+}
 #endif /* defined(TARGET_PPC64) */
 
 /* PowerPC 40x internal IRQ controller */
diff --git a/hw/ppc.h b/hw/ppc.h
index 34f54cf..3ccf134 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -36,6 +36,7 @@ void ppc40x_irq_init (CPUState *env);
 void ppce500_irq_init (CPUState *env);
 void ppc6xx_irq_init (CPUState *env);
 void ppc970_irq_init (CPUState *env);
+void ppcPOWER7_irq_init (CPUState *env);
 
 /* PPC machines for OpenBIOS */
 enum {
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 10341b3..25d0658 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -119,6 +119,8 @@ enum powerpc_mmu_t {
     POWERPC_MMU_64B        = POWERPC_MMU_64 | 0x00000001,
     /* 620 variant (no segment exceptions)                     */
     POWERPC_MMU_620        = POWERPC_MMU_64 | 0x00000002,
+    /* Architecture 2.06 variant                               */
+    POWERPC_MMU_2_06       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG | 0x00000003,
 #endif /* defined(TARGET_PPC64) */
 };
 
@@ -154,6 +156,8 @@ enum powerpc_excp_t {
 #if defined(TARGET_PPC64)
     /* PowerPC 970 exception model      */
     POWERPC_EXCP_970,
+    /* POWER7 exception model           */
+    POWERPC_EXCP_POWER7,
 #endif /* defined(TARGET_PPC64) */
 };
 
@@ -289,6 +293,8 @@ enum powerpc_input_t {
     PPC_FLAGS_INPUT_405,
     /* PowerPC 970 bus                  */
     PPC_FLAGS_INPUT_970,
+    /* PowerPC POWER7 bus               */
+    PPC_FLAGS_INPUT_POWER7,
     /* PowerPC 401 bus                  */
     PPC_FLAGS_INPUT_401,
     /* Freescale RCPU bus               */
@@ -1001,6 +1007,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #define SPR_HSPRG1            (0x131)
 #define SPR_HDSISR            (0x132)
 #define SPR_HDAR              (0x133)
+#define SPR_SPURR             (0x134)
 #define SPR_BOOKE_DBCR0       (0x134)
 #define SPR_IBCR              (0x135)
 #define SPR_PURR              (0x135)
@@ -1625,6 +1632,15 @@ enum {
     PPC970_INPUT_THINT      = 6,
     PPC970_INPUT_NB,
 };
+
+enum {
+    /* POWER7 input pins */
+    POWER7_INPUT_INT        = 0,
+    /* POWER7 probably has other inputs, but we don't care about them
+     * for any existing machine.  We can wire these up when we need
+     * them */
+    POWER7_INPUT_NB,
+};
 #endif
 
 /* Hardware exceptions definitions */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 6712fce..278bee4 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1200,6 +1200,7 @@ static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
         /* Real address are 60 bits long */
         ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
         ctx->prot |= PAGE_WRITE;
@@ -1277,6 +1278,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
 #if defined(TARGET_PPC64)
         case POWERPC_MMU_620:
         case POWERPC_MMU_64B:
+        case POWERPC_MMU_2_06:
 #endif
             if (ret < 0) {
                 /* We didn't match any BAT entry or don't have BATs */
@@ -1376,6 +1378,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
                 case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
+                case POWERPC_MMU_2_06:
 #endif
                     env->exception_index = POWERPC_EXCP_ISI;
                     env->error_code = 0x40000000;
@@ -1485,6 +1488,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
                 case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
+                case POWERPC_MMU_2_06:
 #endif
                     env->exception_index = POWERPC_EXCP_DSI;
                     env->error_code = 0;
@@ -1808,6 +1812,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
 #endif /* defined(TARGET_PPC64) */
         tlb_flush(env, 1);
         break;
@@ -1875,6 +1880,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
 #if defined(TARGET_PPC64)
     case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
         /* tlbie invalidate TLBs for all segments */
         /* XXX: given the fact that there are too many segments to invalidate,
          *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6366424..e2a83c5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -61,6 +61,7 @@ void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
 PPC_IRQ_INIT_FN(40x);
 PPC_IRQ_INIT_FN(6xx);
 PPC_IRQ_INIT_FN(970);
+PPC_IRQ_INIT_FN(POWER7);
 PPC_IRQ_INIT_FN(e500);
 
 /* Generic callbacks:
@@ -3131,6 +3132,35 @@ static void init_excp_970 (CPUPPCState *env)
     env->hreset_vector = 0x0000000000000100ULL;
 #endif
 }
+
+static void init_excp_POWER7 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_DSEG]     = 0x00000380;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_ISEG]     = 0x00000480;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_HDECR]    = 0x00000980;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001800;
+    env->hreset_excp_prefix = 0;
+    /* Hardware reset vector */
+    env->hreset_vector = 0x0000000000000100ULL;
+#endif
+}
 #endif
 
 /*****************************************************************************/
@@ -6312,6 +6342,78 @@ static void init_proc_970MP (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+#if defined(TARGET_PPC64)
+/* POWER7 */
+#define POWERPC_INSNS_POWER7  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
+                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
+                              PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |           \
+                              PPC_FLOAT_STFIWX |                              \
+                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZT |  \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
+                              PPC_64B | PPC_ALTIVEC |                         \
+                              PPC_SEGMENT_64B | PPC_SLBI |                    \
+                              PPC_POPCNTB | PPC_POPCNTWD)
+#define POWERPC_MSRM_POWER7   (0x800000000204FF36ULL)
+#define POWERPC_MMU_POWER7    (POWERPC_MMU_2_06)
+#define POWERPC_EXCP_POWER7   (POWERPC_EXCP_POWER7)
+#define POWERPC_INPUT_POWER7  (PPC_FLAGS_INPUT_POWER7)
+#define POWERPC_BFDM_POWER7   (bfd_mach_ppc64)
+#define POWERPC_FLAG_POWER7   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
+                              POWERPC_FLAG_BUS_CLK)
+#define check_pow_POWER7    check_pow_nocheck
+
+static void init_proc_POWER7 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+#if !defined(CONFIG_USER_ONLY)
+    /* PURR & SPURR: Hack - treat these as aliases for the TB for now */
+    spr_register(env, SPR_PURR,   "PURR",
+                 &spr_read_purr, SPR_NOACCESS,
+                 &spr_read_purr, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPURR,   "SPURR",
+                 &spr_read_purr, SPR_NOACCESS,
+                 &spr_read_purr, SPR_NOACCESS,
+                 0x00000000);
+#endif /* !CONFIG_USER_ONLY */
+    /* Memory management */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    /* XXX : not implemented */
+    spr_register(env, SPR_CTRL, "SPR_CTRLT",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x80800000);
+    spr_register(env, SPR_UCTRL, "SPR_CTRLF",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x80800000);
+    spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+#if !defined(CONFIG_USER_ONLY)
+    env->slb_nr = 32;
+#endif
+    init_excp_POWER7(env);
+    env->dcache_line_size = 128;
+    env->icache_line_size = 128;
+    /* Allocate hardware IRQ controller */
+    ppcPOWER7_irq_init(env);
+    /* Can't find information on what this should be on reset.  This
+     * value is the one used by 74xx processors. */
+    vscr_init(env, 0x00010000);
+}
+#endif /* TARGET_PPC64 */
+
 /* PowerPC 620                                                               */
 #define POWERPC_INSNS_620    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -7034,6 +7136,8 @@ enum {
     CPU_POWERPC_POWER6             = 0x003E0000,
     CPU_POWERPC_POWER6_5           = 0x0F000001, /* POWER6 in POWER5 mode */
     CPU_POWERPC_POWER6A            = 0x0F000002,
+#define CPU_POWERPC_POWER7           CPU_POWERPC_POWER7_v20
+    CPU_POWERPC_POWER7_v20         = 0x003F0200,
     CPU_POWERPC_970                = 0x00390202,
 #define CPU_POWERPC_970FX            CPU_POWERPC_970FX_v31
     CPU_POWERPC_970FX_v10          = 0x00391100,
@@ -8836,6 +8940,9 @@ static const ppc_def_t ppc_defs[] = {
     /* POWER6A                                                               */
     POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6),
 #endif
+    /* POWER7                                                                */
+    POWERPC_DEF("POWER7",        CPU_POWERPC_POWER7,                 POWER7),
+    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7),
     /* PowerPC 970                                                           */
     POWERPC_DEF("970",           CPU_POWERPC_970,                    970),
     /* PowerPC 970FX (G5)                                                    */
commit cdaee00633cfac7338d8dd0ba3e8766d5bdb1cec
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:18 2011 +1100

    Support 1T segments on ppc
    
    Traditionally, the "segments" used for the two-stage translation used on
    powerpc MMUs were 256MB in size.  This was the only option on all hash
    page table based 32-bit powerpc cpus, and on the earlier 64-bit hash page
    table based cpus.  However, newer 64-bit cpus also permit 1TB segments
    
    This patch adds support for 1TB segment translation to the qemu code.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index fd2dfcd..10341b3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -114,6 +114,7 @@ enum powerpc_mmu_t {
     POWERPC_MMU_601        = 0x0000000A,
 #if defined(TARGET_PPC64)
 #define POWERPC_MMU_64       0x00010000
+#define POWERPC_MMU_1TSEG    0x00020000
     /* 64 bits PowerPC MMU                                     */
     POWERPC_MMU_64B        = POWERPC_MMU_64 | 0x00000001,
     /* 620 variant (no segment exceptions)                     */
@@ -382,9 +383,11 @@ struct ppc_slb_t {
 
 /* Bits in the SLB VSID word */
 #define SLB_VSID_SHIFT          12
+#define SLB_VSID_SHIFT_1T       24
 #define SLB_VSID_SSIZE_SHIFT    62
 #define SLB_VSID_B              0xc000000000000000ULL
 #define SLB_VSID_B_256M         0x0000000000000000ULL
+#define SLB_VSID_B_1T           0x4000000000000000ULL
 #define SLB_VSID_VSID           0x3FFFFFFFFFFFF000ULL
 #define SLB_VSID_PTEM           (SLB_VSID_B | SLB_VSID_VSID)
 #define SLB_VSID_KS             0x0000000000000800ULL
@@ -398,6 +401,10 @@ struct ppc_slb_t {
 #define SEGMENT_SHIFT_256M      28
 #define SEGMENT_MASK_256M       (~((1ULL << SEGMENT_SHIFT_256M) - 1))
 
+#define SEGMENT_SHIFT_1T        40
+#define SEGMENT_MASK_1T         (~((1ULL << SEGMENT_SHIFT_1T) - 1))
+
+
 /*****************************************************************************/
 /* Machine state register bits definition                                    */
 #define MSR_SF   63 /* Sixty-four-bit mode                            hflags */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index ae8001c..6712fce 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -675,19 +675,26 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
 #if defined(TARGET_PPC64)
 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
 {
-    uint64_t esid;
+    uint64_t esid_256M, esid_1T;
     int n;
 
     LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
 
-    esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+    esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+    esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
 
     for (n = 0; n < env->slb_nr; n++) {
         ppc_slb_t *slb = &env->slb[n];
 
         LOG_SLB("%s: slot %d %016" PRIx64 " %016"
                     PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
-        if (slb->esid == esid) {
+        /* We check for 1T matches on all MMUs here - if the MMU
+         * doesn't have 1T segment support, we will have prevented 1T
+         * entries from being inserted in the slbmte code. */
+        if (((slb->esid == esid_256M) &&
+             ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
+            || ((slb->esid == esid_1T) &&
+                ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
             return slb;
         }
     }
@@ -740,14 +747,20 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 {
     int slot = rb & 0xfff;
-    uint64_t esid = rb & ~0xfff;
     ppc_slb_t *slb = &env->slb[slot];
 
-    if (slot >= env->slb_nr) {
-        return -1;
+    if (rb & (0x1000 - env->slb_nr)) {
+        return -1; /* Reserved bits set or slot too high */
+    }
+    if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
+        return -1; /* Bad segment size */
+    }
+    if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
+        return -1; /* 1T segment on MMU that doesn't support it */
     }
 
-    slb->esid = esid;
+    /* Mask out the slot number as we store the entry */
+    slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
     slb->vsid = rs;
 
     LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
@@ -799,6 +812,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
     if (env->mmu_model & POWERPC_MMU_64) {
         ppc_slb_t *slb;
         target_ulong pageaddr;
+        int segment_bits;
 
         LOG_MMU("Check SLBs\n");
         slb = slb_lookup(env, eaddr);
@@ -806,7 +820,14 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
             return -5;
         }
 
-        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+        if (slb->vsid & SLB_VSID_B) {
+            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
+            segment_bits = 40;
+        } else {
+            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+            segment_bits = 28;
+        }
+
         target_page_bits = (slb->vsid & SLB_VSID_L)
             ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
         ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
@@ -814,11 +835,16 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         ds = 0;
         ctx->nx = !!(slb->vsid & SLB_VSID_N);
 
-        pageaddr = eaddr & ((1ULL << 28) - (1ULL << target_page_bits));
-        /* XXX: this is false for 1 TB segments */
-        hash = vsid ^ (pageaddr >> target_page_bits);
+        pageaddr = eaddr & ((1ULL << segment_bits)
+                            - (1ULL << target_page_bits));
+        if (slb->vsid & SLB_VSID_B) {
+            hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
+        } else {
+            hash = vsid ^ (pageaddr >> target_page_bits);
+        }
         /* Only 5 bits of the page index are used in the AVPN */
-        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & 0x0F80);
+        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
+            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
     } else
 #endif /* defined(TARGET_PPC64) */
     {
commit 256cebe5d17477cd1443f47a9bd5ca35ca0dbc9c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:17 2011 +1100

    Better factor the ppc hash translation path
    
    Currently the path handling hash page table translation in get_segment()
    has a mix of common and 32 or 64 bit specific code.  However the
    division is not done terribly well which results in a lot of messy code
    flipping between common and divided paths.
    
    This patch improves the organization, consolidating several divided paths
    into one.  This in turn allows simplification of some code in
    get_segment(), removing a number of ugly interim variables.
    
    This new factorization will also make it easier to add support for the 1T
    segments added in newer CPUs.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index cee1057..fd2dfcd 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -386,6 +386,7 @@ struct ppc_slb_t {
 #define SLB_VSID_B              0xc000000000000000ULL
 #define SLB_VSID_B_256M         0x0000000000000000ULL
 #define SLB_VSID_VSID           0x3FFFFFFFFFFFF000ULL
+#define SLB_VSID_PTEM           (SLB_VSID_B | SLB_VSID_VSID)
 #define SLB_VSID_KS             0x0000000000000800ULL
 #define SLB_VSID_KP             0x0000000000000400ULL
 #define SLB_VSID_N              0x0000000000000200ULL /* no-execute */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 0efa2a8..ae8001c 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -661,29 +661,15 @@ static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
     return ret;
 }
 
-static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
-                             int type, int target_page_bits)
-{
-    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
-}
-
-#if defined(TARGET_PPC64)
-static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
-                             int type, int target_page_bits)
-{
-    return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
-}
-#endif
-
 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
                            int type, int target_page_bits)
 {
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64)
-        return find_pte64(env, ctx, h, rw, type, target_page_bits);
+        return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
 #endif
 
-    return find_pte32(env, ctx, h, rw, type, target_page_bits);
+    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
 }
 
 #if defined(TARGET_PPC64)
@@ -803,14 +789,16 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                               target_ulong eaddr, int rw, int type)
 {
     target_phys_addr_t hash;
-    target_ulong sr, vsid, pgidx, page_mask;
+    target_ulong vsid;
     int ds, pr, target_page_bits;
     int ret, ret2;
 
     pr = msr_pr;
+    ctx->eaddr = eaddr;
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64) {
         ppc_slb_t *slb;
+        target_ulong pageaddr;
 
         LOG_MMU("Check SLBs\n");
         slb = slb_lookup(env, eaddr);
@@ -819,19 +807,24 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         }
 
         vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
-        page_mask = ~SEGMENT_MASK_256M;
         target_page_bits = (slb->vsid & SLB_VSID_L)
             ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
         ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
                       : (slb->vsid & SLB_VSID_KS));
         ds = 0;
         ctx->nx = !!(slb->vsid & SLB_VSID_N);
-        ctx->eaddr = eaddr;
+
+        pageaddr = eaddr & ((1ULL << 28) - (1ULL << target_page_bits));
+        /* XXX: this is false for 1 TB segments */
+        hash = vsid ^ (pageaddr >> target_page_bits);
+        /* Only 5 bits of the page index are used in the AVPN */
+        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & 0x0F80);
     } else
 #endif /* defined(TARGET_PPC64) */
     {
+        target_ulong sr, pgidx;
+
         sr = env->sr[eaddr >> 28];
-        page_mask = 0x0FFFFFFF;
         ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
                     ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
         ds = sr & 0x80000000 ? 1 : 0;
@@ -843,6 +836,9 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                 " ir=%d dr=%d pr=%d %d t=%d\n",
                 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
                 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
+        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
+        hash = vsid ^ pgidx;
+        ctx->ptem = (vsid << 7) | (pgidx >> 10);
     }
     LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
             ctx->key, ds, ctx->nx, vsid);
@@ -851,36 +847,12 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         /* Check if instruction fetch is allowed, if needed */
         if (type != ACCESS_CODE || ctx->nx == 0) {
             /* Page address translation */
-            pgidx = (eaddr & page_mask) >> target_page_bits;
-#if defined(TARGET_PPC64)
-            if (env->mmu_model & POWERPC_MMU_64) {
-                /* XXX: this is false for 1 TB segments */
-                hash = vsid ^ pgidx;
-            } else
-#endif
-            {
-                hash = vsid ^ pgidx;
-            }
             LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
                     " hash " TARGET_FMT_plx "\n",
                     env->htab_base, env->htab_mask, hash);
             ctx->hash[0] = hash;
             ctx->hash[1] = ~hash;
 
-#if defined(TARGET_PPC64)
-            if (env->mmu_model & POWERPC_MMU_64) {
-                /* Only 5 bits of the page index are used in the AVPN */
-                if (target_page_bits > 23) {
-                    ctx->ptem = (vsid << 12) |
-                                ((pgidx << (target_page_bits - 16)) & 0xF80);
-                } else {
-                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
-                }
-            } else
-#endif
-            {
-                ctx->ptem = (vsid << 7) | (pgidx >> 10);
-            }
             /* Initialize real address with an invalid value */
             ctx->raddr = (target_phys_addr_t)-1ULL;
             if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
@@ -889,9 +861,9 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
             } else {
                 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                        " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                        " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
                         " hash=" TARGET_FMT_plx "\n",
-                        env->htab_base, env->htab_mask, vsid, pgidx,
+                        env->htab_base, env->htab_mask, vsid, ctx->ptem,
                         ctx->hash[0]);
                 /* Primary table lookup */
                 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
@@ -902,8 +874,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                                 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
                                 " hash=" TARGET_FMT_plx " pg_addr="
                                 TARGET_FMT_plx "\n", env->htab_base,
-                                env->htab_mask, vsid, pgidx, hash,
-                                ctx->hash[1]);
+                                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
                     ret2 = find_pte(env, ctx, 1, rw, type,
                                     target_page_bits);
                     if (ret2 != -1)
commit fda6a0ecc61926ea1af6a85ab47a4ae47a6fe0a7
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:16 2011 +1100

    Use "hash" more consistently in ppc mmu code
    
    Currently, get_segment() has a variable called hash.  However it doesn't
    (quite) get the hash value for the ppc hashed page table.  Instead it
    gets the hash shifted - effectively the offset of the hash bucket within
    the hash page table.
    
    As well, as being different to the normal use of plain "hash" in the
    architecture documentation, this usage necessitates some awkward 32/64
    dependent masks and shifts which clutter up the path in get_segment().
    
    This patch alters the code to use raw hash values through get_segment()
    including storing raw hashes instead of pte group offsets in the ctx
    structure.  This cleans up the path noticeably.
    
    This does necessitate 32/64 dependent shifts when the hash values are
    taken out of the ctx structure and used, but those paths already have
    32/64 bit variants so this is less awkward than it was in get_segment().
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ead4566..cee1057 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -367,6 +367,9 @@ union ppc_tlb_t {
 #define SDR_64_HTABSIZE        0x000000000000001FULL
 #endif /* defined(TARGET_PPC64 */
 
+#define HASH_PTE_SIZE_32       8
+#define HASH_PTE_SIZE_64       16
+
 typedef struct ppc_slb_t ppc_slb_t;
 struct ppc_slb_t {
     uint64_t esid;
@@ -744,7 +747,7 @@ struct mmu_ctx_t {
     target_phys_addr_t raddr;      /* Real address              */
     target_phys_addr_t eaddr;      /* Effective address         */
     int prot;                      /* Protection bits           */
-    target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
+    target_phys_addr_t hash[2];    /* Pagetable hash values     */
     target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
     int nx;                        /* Non-execute area          */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 68d2d9c..0efa2a8 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -567,21 +567,30 @@ static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
     return ret;
 }
 
+static inline target_phys_addr_t get_pteg_offset(CPUState *env,
+                                                 target_phys_addr_t hash,
+                                                 int pte_size)
+{
+    return (hash * pte_size * 8) & env->htab_mask;
+}
+
 /* PTE table lookup */
-static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
-                            int type, int target_page_bits)
+static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
+                            int rw, int type, int target_page_bits)
 {
-    target_ulong base, pte0, pte1;
+    target_phys_addr_t pteg_off;
+    target_ulong pte0, pte1;
     int i, good = -1;
     int ret, r;
 
     ret = -1; /* No entry found */
-    base = ctx->pg_addr[h];
+    pteg_off = get_pteg_offset(env, ctx->hash[h],
+                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
     for (i = 0; i < 8; i++) {
 #if defined(TARGET_PPC64)
         if (is_64b) {
-            pte0 = ldq_phys(base + (i * 16));
-            pte1 = ldq_phys(base + (i * 16) + 8);
+            pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
+            pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
 
             /* We have a TLB that saves 4K pages, so let's
              * split a huge page to 4k chunks */
@@ -592,17 +601,17 @@ static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
             r = pte64_check(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
                     TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                    base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
+                    pteg_base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
                     (int)((pte0 >> 1) & 1), ctx->ptem);
         } else
 #endif
         {
-            pte0 = ldl_phys(base + (i * 8));
-            pte1 =  ldl_phys(base + (i * 8) + 4);
+            pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
+            pte1 =  ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
             r = pte32_check(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
                     TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                    base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
+                    pteg_base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
                     (int)((pte0 >> 6) & 1), ctx->ptem);
         }
         switch (r) {
@@ -638,11 +647,13 @@ static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
         if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
 #if defined(TARGET_PPC64)
             if (is_64b) {
-                stq_phys_notdirty(base + (good * 16) + 8, pte1);
+                stq_phys_notdirty(env->htab_base + pteg_off + (good * 16) + 8,
+                                  pte1);
             } else
 #endif
             {
-                stl_phys_notdirty(base + (good * 8) + 4, pte1);
+                stl_phys_notdirty(env->htab_base + pteg_off + (good * 8) + 4,
+                                  pte1);
             }
         }
     }
@@ -650,17 +661,17 @@ static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
     return ret;
 }
 
-static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
-                             int target_page_bits)
+static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
+                             int type, int target_page_bits)
 {
-    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
+    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
 }
 
 #if defined(TARGET_PPC64)
-static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
-                             int target_page_bits)
+static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
+                             int type, int target_page_bits)
 {
-    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
+    return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
 }
 #endif
 
@@ -669,10 +680,10 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
 {
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64)
-        return find_pte64(ctx, h, rw, type, target_page_bits);
+        return find_pte64(env, ctx, h, rw, type, target_page_bits);
 #endif
 
-    return find_pte32(ctx, h, rw, type, target_page_bits);
+    return find_pte32(env, ctx, h, rw, type, target_page_bits);
 }
 
 #if defined(TARGET_PPC64)
@@ -788,19 +799,12 @@ int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
 #endif /* defined(TARGET_PPC64) */
 
 /* Perform segment based translation */
-static inline target_phys_addr_t get_pgaddr(target_phys_addr_t htab_base,
-                                            target_phys_addr_t htab_mask,
-                                            target_phys_addr_t hash)
-{
-    return htab_base | (hash & htab_mask);
-}
-
 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                               target_ulong eaddr, int rw, int type)
 {
     target_phys_addr_t hash;
-    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
-    int ds, vsid_sh, pr, target_page_bits;
+    target_ulong sr, vsid, pgidx, page_mask;
+    int ds, pr, target_page_bits;
     int ret, ret2;
 
     pr = msr_pr;
@@ -823,8 +827,6 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         ds = 0;
         ctx->nx = !!(slb->vsid & SLB_VSID_N);
         ctx->eaddr = eaddr;
-        vsid_mask = 0x00003FFFFFFFFF80ULL;
-        vsid_sh = 7;
     } else
 #endif /* defined(TARGET_PPC64) */
     {
@@ -835,8 +837,6 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         ds = sr & 0x80000000 ? 1 : 0;
         ctx->nx = sr & 0x10000000 ? 1 : 0;
         vsid = sr & 0x00FFFFFF;
-        vsid_mask = 0x01FFFFC0;
-        vsid_sh = 6;
         target_page_bits = TARGET_PAGE_BITS;
         LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
                 TARGET_FMT_lx " lr=" TARGET_FMT_lx
@@ -851,27 +851,22 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         /* Check if instruction fetch is allowed, if needed */
         if (type != ACCESS_CODE || ctx->nx == 0) {
             /* Page address translation */
-            /* Primary table address */
             pgidx = (eaddr & page_mask) >> target_page_bits;
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
                 /* XXX: this is false for 1 TB segments */
-                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+                hash = vsid ^ pgidx;
             } else
 #endif
             {
-                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+                hash = vsid ^ pgidx;
             }
             LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
                     " hash " TARGET_FMT_plx "\n",
                     env->htab_base, env->htab_mask, hash);
-            ctx->pg_addr[0] = get_pgaddr(env->htab_base, env->htab_mask, hash);
-            /* Secondary table address */
-            hash = (~hash) & vsid_mask;
-            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
-                    " hash " TARGET_FMT_plx "\n",
-                    env->htab_base, env->htab_mask, hash);
-            ctx->pg_addr[1] = get_pgaddr(env->htab_base, env->htab_mask, hash);
+            ctx->hash[0] = hash;
+            ctx->hash[1] = ~hash;
+
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
                 /* Only 5 bits of the page index are used in the AVPN */
@@ -895,9 +890,9 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
             } else {
                 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                         " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                        " hash=" TARGET_FMT_plx " pg_addr=" TARGET_FMT_plx "\n",
-                        env->htab_base, env->htab_mask, vsid, pgidx, hash,
-                        ctx->pg_addr[0]);
+                        " hash=" TARGET_FMT_plx "\n",
+                        env->htab_base, env->htab_mask, vsid, pgidx,
+                        ctx->hash[0]);
                 /* Primary table lookup */
                 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
                 if (ret < 0) {
@@ -908,7 +903,7 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                                 " hash=" TARGET_FMT_plx " pg_addr="
                                 TARGET_FMT_plx "\n", env->htab_base,
                                 env->htab_mask, vsid, pgidx, hash,
-                                ctx->pg_addr[1]);
+                                ctx->hash[1]);
                     ret2 = find_pte(env, ctx, 1, rw, type,
                                     target_page_bits);
                     if (ret2 != -1)
@@ -1460,8 +1455,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
                 tlb_miss:
                     env->error_code |= ctx.key << 19;
-                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
-                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
+                    env->spr[SPR_HASH1] = env->htab_base +
+                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
+                    env->spr[SPR_HASH2] = env->htab_base +
+                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
                     break;
                 case POWERPC_MMU_SOFT_74xx:
                     if (rw == 1) {
commit bb593904c18e22ea0671dfa1b02e24982f2bf0ea
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:15 2011 +1100

    Parse SDR1 on mtspr instead of at translate time
    
    On ppc machines with hash table MMUs, the special purpose register SDR1
    contains both the base address of the encoded size (hashed) page tables.
    
    At present, we interpret the SDR1 value within the address translation
    path.  But because the encodings of the size for 32-bit and 64-bit are
    different this makes for a confusing branch on the MMU type with a bunch
    of curly shifts and masks in the middle of the translate path.
    
    This patch cleans things up by moving the interpretation on SDR1 into the
    helper function handling the write to the register.  This leaves a simple
    pre-sanitized base address and mask for the hash table in the CPUState
    structure which is easier to work with in the translation path.
    
    This makes the translation path more readable.  It addresses the FIXME
    comment currently in the mtsdr1 helper, by validating the SDR1 value during
    interpretation.  Finally it opens the way for emulating a pSeries-style
    partition where the hash table used for translation is not mapped into
    the guests's RAM.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/monitor.c b/monitor.c
index 76a8207..f1a08dc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3462,7 +3462,7 @@ static const MonitorDef monitor_defs[] = {
     { "asr", offsetof(CPUState, asr) },
 #endif
     /* Segment registers */
-    { "sdr1", offsetof(CPUState, sdr1) },
+    { "sdr1", offsetof(CPUState, spr[SPR_SDR1]) },
     { "sr0", offsetof(CPUState, sr[0]) },
     { "sr1", offsetof(CPUState, sr[1]) },
     { "sr2", offsetof(CPUState, sr[2]) },
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 37dde39..ead4566 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -359,6 +359,14 @@ union ppc_tlb_t {
 };
 #endif
 
+#define SDR_32_HTABORG         0xFFFF0000UL
+#define SDR_32_HTABMASK        0x000001FFUL
+
+#if defined(TARGET_PPC64)
+#define SDR_64_HTABORG         0xFFFFFFFFFFFC0000ULL
+#define SDR_64_HTABSIZE        0x000000000000001FULL
+#endif /* defined(TARGET_PPC64 */
+
 typedef struct ppc_slb_t ppc_slb_t;
 struct ppc_slb_t {
     uint64_t esid;
@@ -642,7 +650,8 @@ struct CPUPPCState {
     int slb_nr;
 #endif
     /* segment registers */
-    target_ulong sdr1;
+    target_phys_addr_t htab_base;
+    target_phys_addr_t htab_mask;
     target_ulong sr[32];
     /* BATs */
     int nb_BATs;
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 7ca33cb..68d2d9c 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -788,20 +788,19 @@ int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
 #endif /* defined(TARGET_PPC64) */
 
 /* Perform segment based translation */
-static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
-                                            int sdr_sh,
-                                            target_phys_addr_t hash,
-                                            target_phys_addr_t mask)
+static inline target_phys_addr_t get_pgaddr(target_phys_addr_t htab_base,
+                                            target_phys_addr_t htab_mask,
+                                            target_phys_addr_t hash)
 {
-    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
+    return htab_base | (hash & htab_mask);
 }
 
 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                               target_ulong eaddr, int rw, int type)
 {
-    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
+    target_phys_addr_t hash;
     target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
-    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
+    int ds, vsid_sh, pr, target_page_bits;
     int ret, ret2;
 
     pr = msr_pr;
@@ -826,8 +825,6 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         ctx->eaddr = eaddr;
         vsid_mask = 0x00003FFFFFFFFF80ULL;
         vsid_sh = 7;
-        sdr_sh = 18;
-        sdr_mask = 0x3FF80;
     } else
 #endif /* defined(TARGET_PPC64) */
     {
@@ -840,8 +837,6 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         vsid = sr & 0x00FFFFFF;
         vsid_mask = 0x01FFFFC0;
         vsid_sh = 6;
-        sdr_sh = 16;
-        sdr_mask = 0xFFC0;
         target_page_bits = TARGET_PAGE_BITS;
         LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
                 TARGET_FMT_lx " lr=" TARGET_FMT_lx
@@ -857,29 +852,26 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
         if (type != ACCESS_CODE || ctx->nx == 0) {
             /* Page address translation */
             /* Primary table address */
-            sdr = env->sdr1;
             pgidx = (eaddr & page_mask) >> target_page_bits;
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
-                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
                 /* XXX: this is false for 1 TB segments */
                 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
             } else
 #endif
             {
-                htab_mask = sdr & 0x000001FF;
                 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
             }
-            mask = (htab_mask << sdr_sh) | sdr_mask;
-            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
-                    " mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-                    sdr, sdr_sh, hash, mask, page_mask);
-            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
+            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+                    " hash " TARGET_FMT_plx "\n",
+                    env->htab_base, env->htab_mask, hash);
+            ctx->pg_addr[0] = get_pgaddr(env->htab_base, env->htab_mask, hash);
             /* Secondary table address */
             hash = (~hash) & vsid_mask;
-            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
-                    " mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask);
-            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
+            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+                    " hash " TARGET_FMT_plx "\n",
+                    env->htab_base, env->htab_mask, hash);
+            ctx->pg_addr[1] = get_pgaddr(env->htab_base, env->htab_mask, hash);
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
                 /* Only 5 bits of the page index are used in the AVPN */
@@ -901,19 +893,22 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
                 /* Software TLB search */
                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
             } else {
-                LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
-                        "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
-                        " pg_addr=" TARGET_FMT_plx "\n",
-                        sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
+                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                        " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                        " hash=" TARGET_FMT_plx " pg_addr=" TARGET_FMT_plx "\n",
+                        env->htab_base, env->htab_mask, vsid, pgidx, hash,
+                        ctx->pg_addr[0]);
                 /* Primary table lookup */
                 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
                 if (ret < 0) {
                     /* Secondary table lookup */
                     if (eaddr != 0xEFFFFFFF)
-                        LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
-                                "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
-                                " pg_addr=" TARGET_FMT_plx "\n", sdr, vsid,
-                                pgidx, hash, ctx->pg_addr[1]);
+                        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                                " hash=" TARGET_FMT_plx " pg_addr="
+                                TARGET_FMT_plx "\n", env->htab_base,
+                                env->htab_mask, vsid, pgidx, hash,
+                                ctx->pg_addr[1]);
                     ret2 = find_pte(env, ctx, 1, rw, type,
                                     target_page_bits);
                     if (ret2 != -1)
@@ -1919,11 +1914,26 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
 {
     LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
-    if (env->sdr1 != value) {
-        /* XXX: for PowerPC 64, should check that the HTABSIZE value
-         *      is <= 28
-         */
-        env->sdr1 = value;
+    if (env->spr[SPR_SDR1] != value) {
+        env->spr[SPR_SDR1] = value;
+#if defined(TARGET_PPC64)
+        if (env->mmu_model & POWERPC_MMU_64) {
+            target_ulong htabsize = value & SDR_64_HTABSIZE;
+
+            if (htabsize > 28) {
+                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
+                        " stored in SDR1\n", htabsize);
+                htabsize = 28;
+            }
+            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
+            env->htab_base = value & SDR_64_HTABORG;
+        } else
+#endif /* defined(TARGET_PPC64) */
+        {
+            /* FIXME: Should check for valid HTABMASK values */
+            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
+            env->htab_base = value & SDR_32_HTABORG;
+        }
         tlb_flush(env, 1);
     }
 }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 0e2e67b..2cfb24b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -169,7 +169,7 @@ int kvm_arch_get_registers(CPUState *env)
 
 #ifdef KVM_CAP_PPC_SEGSTATE
     if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
-        env->sdr1 = sregs.u.s.sdr1;
+        ppc_store_sdr1(env, sregs.u.s.sdr1);
 
         /* Sync SLB */
 #ifdef TARGET_PPC64
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 67de951..0c1986e 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -37,7 +37,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_betls(f, &env->asr);
     qemu_put_sbe32s(f, &env->slb_nr);
 #endif
-    qemu_put_betls(f, &env->sdr1);
+    qemu_put_betls(f, &env->spr[SPR_SDR1]);
     for (i = 0; i < 32; i++)
         qemu_put_betls(f, &env->sr[i]);
     for (i = 0; i < 2; i++)
@@ -93,6 +93,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
     CPUState *env = (CPUState *)opaque;
     unsigned int i, j;
+    target_ulong sdr1;
 
     for (i = 0; i < 32; i++)
         qemu_get_betls(f, &env->gpr[i]);
@@ -124,7 +125,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_betls(f, &env->asr);
     qemu_get_sbe32s(f, &env->slb_nr);
 #endif
-    qemu_get_betls(f, &env->sdr1);
+    qemu_get_betls(f, &sdr1);
     for (i = 0; i < 32; i++)
         qemu_get_betls(f, &env->sr[i]);
     for (i = 0; i < 2; i++)
@@ -152,6 +153,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
 #endif
     for (i = 0; i < 1024; i++)
         qemu_get_betls(f, &env->spr[i]);
+    ppc_store_sdr1(env, sdr1);
     qemu_get_be32s(f, &env->vscr);
     qemu_get_be64s(f, &env->spe_acc);
     qemu_get_be32s(f, &env->spe_fscr);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8868135..090795b 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9126,7 +9126,7 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #if !defined(CONFIG_USER_ONLY)
     cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
                 TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-                env->sdr1);
+                env->spr[SPR_SDR1]);
 #endif
 
 #undef RGPL
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index bca85d5..6366424 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -343,11 +343,6 @@ static void spr_write_dbatl_h (void *opaque, int sprn, int gprn)
 }
 
 /* SDR1 */
-static void spr_read_sdr1 (void *opaque, int gprn, int sprn)
-{
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, sdr1));
-}
-
 static void spr_write_sdr1 (void *opaque, int sprn, int gprn)
 {
     gen_helper_store_sdr1(cpu_gpr[gprn]);
@@ -671,7 +666,7 @@ static void gen_spr_ne_601 (CPUPPCState *env)
     /* Memory management */
     spr_register(env, SPR_SDR1, "SDR1",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_sdr1, &spr_write_sdr1,
+                 &spr_read_generic, &spr_write_sdr1,
                  0x00000000);
 }
 
commit 8500e3a91292f253002783da267f3b08aead86c1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:14 2011 +1100

    Clean up slb_lookup() function
    
    The slb_lookup() function, used in the ppc translation path returns a
    number of slb entry fields in reference parameters.  However, only one
    of the two callers of slb_lookup() actually wants this information.
    
    This patch, therefore, makes slb_lookup() return a simple pointer to the
    located SLB entry (or NULL), and the caller which needs the fields can
    extract them itself.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index b9621d2..7ca33cb 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -676,9 +676,7 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
 }
 
 #if defined(TARGET_PPC64)
-static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
-                             target_ulong *vsid, target_ulong *page_mask,
-                             int *attr, int *target_page_bits)
+static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
 {
     uint64_t esid;
     int n;
@@ -693,19 +691,11 @@ static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
         LOG_SLB("%s: slot %d %016" PRIx64 " %016"
                     PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
         if (slb->esid == esid) {
-            *vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
-            *page_mask = ~SEGMENT_MASK_256M;
-            *attr = slb->vsid & SLB_VSID_ATTR;
-            if (target_page_bits) {
-                *target_page_bits = (slb->vsid & SLB_VSID_L)
-                    ? TARGET_PAGE_BITS_16M
-                    : TARGET_PAGE_BITS;
-            }
-            return n;
+            return slb;
         }
     }
 
-    return -5;
+    return NULL;
 }
 
 void ppc_slb_invalidate_all (CPUPPCState *env)
@@ -732,18 +722,13 @@ void ppc_slb_invalidate_all (CPUPPCState *env)
 
 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 {
-    target_ulong vsid, page_mask;
-    int attr;
-    int n;
     ppc_slb_t *slb;
 
-    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
-    if (n < 0) {
+    slb = slb_lookup(env, T0);
+    if (!slb) {
         return;
     }
 
-    slb = &env->slb[n];
-
     if (slb->esid & SLB_ESID_V) {
         slb->esid &= ~SLB_ESID_V;
 
@@ -822,16 +807,22 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
     pr = msr_pr;
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64) {
-        int attr;
+        ppc_slb_t *slb;
 
         LOG_MMU("Check SLBs\n");
-        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
-                         &target_page_bits);
-        if (ret < 0)
-            return ret;
-        ctx->key = !!(pr ? (attr & SLB_VSID_KP) : (attr & SLB_VSID_KS));
+        slb = slb_lookup(env, eaddr);
+        if (!slb) {
+            return -5;
+        }
+
+        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+        page_mask = ~SEGMENT_MASK_256M;
+        target_page_bits = (slb->vsid & SLB_VSID_L)
+            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
+                      : (slb->vsid & SLB_VSID_KS));
         ds = 0;
-        ctx->nx = !!(attr & SLB_VSID_N);
+        ctx->nx = !!(slb->vsid & SLB_VSID_N);
         ctx->eaddr = eaddr;
         vsid_mask = 0x00003FFFFFFFFF80ULL;
         vsid_sh = 7;
commit eaabeef2688cdc7da462e9389fce64b1178de8ce
Author: David Gibson <dwg at au1.ibm.com>
Date:   Fri Apr 1 15:15:13 2011 +1100

    Correct ppc popcntb logic, implement popcntw and popcntd
    
    qemu already includes support for the popcntb instruction introduced
    in POWER5 (although it doesn't actually allow you to choose POWER5).
    
    However, the logic is slightly incorrect: it will generate results
    truncated to 32-bits when the CPU is in 32-bit mode.  This is not
    normal for powerpc - generally arithmetic instructions on a 64-bit
    powerpc cpu will generate full 64 bit results, it's just that only the
    low 32 bits will be significant for condition codes.
    
    This patch corrects this nit, which actually simplifies the code slightly.
    
    In addition, this patch implements the popcntw and popcntd
    instructions added in POWER7, in preparation for allowing POWER7 as an
    emulated CPU.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index f293f85..37dde39 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1505,6 +1505,8 @@ enum {
     PPC_DCRX           = 0x2000000000000000ULL,
     /* user-mode DCR access, implemented in PowerPC 460                      */
     PPC_DCRUX          = 0x4000000000000000ULL,
+    /* popcntw and popcntd instructions                                      */
+    PPC_POPCNTWD       = 0x8000000000000000ULL,
 };
 
 /*****************************************************************************/
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 2b4744d..7c02be9 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -38,10 +38,11 @@ DEF_HELPER_2(mulldo, i64, i64, i64)
 
 DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
 DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
 DEF_HELPER_2(sraw, tl, tl, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
-DEF_HELPER_FLAGS_1(popcntb_64, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
 DEF_HELPER_2(srad, tl, tl, tl)
 #endif
 
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index aa2e8ba..b1b883d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -499,6 +499,50 @@ target_ulong helper_srad (target_ulong value, target_ulong shift)
 }
 #endif
 
+#if defined(TARGET_PPC64)
+target_ulong helper_popcntb (target_ulong val)
+{
+    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
+                                           0x5555555555555555ULL);
+    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
+                                           0x3333333333333333ULL);
+    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
+                                           0x0f0f0f0f0f0f0f0fULL);
+    return val;
+}
+
+target_ulong helper_popcntw (target_ulong val)
+{
+    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
+                                           0x5555555555555555ULL);
+    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
+                                           0x3333333333333333ULL);
+    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
+                                           0x0f0f0f0f0f0f0f0fULL);
+    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
+                                           0x00ff00ff00ff00ffULL);
+    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
+                                           0x0000ffff0000ffffULL);
+    return val;
+}
+
+target_ulong helper_popcntd (target_ulong val)
+{
+    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
+                                           0x5555555555555555ULL);
+    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
+                                           0x3333333333333333ULL);
+    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
+                                           0x0f0f0f0f0f0f0f0fULL);
+    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
+                                           0x00ff00ff00ff00ffULL);
+    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
+                                           0x0000ffff0000ffffULL);
+    val = (val & 0x00000000ffffffffULL) + ((val >> 32) &
+                                           0x00000000ffffffffULL);
+    return val;
+}
+#else
 target_ulong helper_popcntb (target_ulong val)
 {
     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
@@ -507,12 +551,13 @@ target_ulong helper_popcntb (target_ulong val)
     return val;
 }
 
-#if defined(TARGET_PPC64)
-target_ulong helper_popcntb_64 (target_ulong val)
+target_ulong helper_popcntw (target_ulong val)
 {
-    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
-    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
-    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
+    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
+    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
+    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
+    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
+    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
     return val;
 }
 #endif
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 4252508..8868135 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1483,13 +1483,21 @@ static void gen_xoris(DisasContext *ctx)
 /* popcntb : PowerPC 2.03 specification */
 static void gen_popcntb(DisasContext *ctx)
 {
+    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+}
+
+static void gen_popcntw(DisasContext *ctx)
+{
+    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+}
+
 #if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
-        gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
-    else
-#endif
-        gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+/* popcntd: PowerPC 2.06 specification */
+static void gen_popcntd(DisasContext *ctx)
+{
+    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
 }
+#endif
 
 #if defined(TARGET_PPC64)
 /* extsw & extsw. */
@@ -8226,7 +8234,9 @@ GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
+GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
 #if defined(TARGET_PPC64)
+GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
 GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
 #endif
 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
commit 3a7f009abc010827815f10805e3558aa64c98e59
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:12 2011 +1100

    Implement missing parts of the logic for the POWER PURR
    
    The PURR (Processor Utilization Resource Register) is a register found
    on recent POWER CPUs.  The guts of implementing it at least enough to
    get by are already present in qemu, however some of the helper
    functions needed to actually wire it up are missing.
    
    This patch adds the necessary glue, so that the PURR can be wired up
    when we implement newer POWER CPU targets which include it.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 1a69cf8..2b4744d 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -376,6 +376,7 @@ DEF_HELPER_0(load_601_rtcu, tl)
 #if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
 DEF_HELPER_1(store_asr, void, tl)
+DEF_HELPER_0(load_purr, tl)
 #endif
 DEF_HELPER_1(store_sdr1, void, tl)
 DEF_HELPER_1(store_tbl, void, tl)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index bdb1f17..aa2e8ba 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -86,6 +86,13 @@ target_ulong helper_load_atbu (void)
     return cpu_ppc_load_atbu(env);
 }
 
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+target_ulong helper_load_purr (void)
+{
+    return (target_ulong)cpu_ppc_load_purr(env);
+}
+#endif
+
 target_ulong helper_load_601_rtcl (void)
 {
     return cpu_ppc601_load_rtcl(env);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7c08b1c..bca85d5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -251,6 +251,14 @@ static void spr_write_atbu (void *opaque, int sprn, int gprn)
 {
     gen_helper_store_atbu(cpu_gpr[gprn]);
 }
+
+#if defined(TARGET_PPC64)
+__attribute__ (( unused ))
+static void spr_read_purr (void *opaque, int gprn, int sprn)
+{
+    gen_helper_load_purr(cpu_gpr[gprn]);
+}
+#endif
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
commit efdef95fee7e150ac065e7b33ffbebd09a5ac83c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:11 2011 +1100

    Implement PowerPC slbmfee and slbmfev instructions
    
    For a 64-bit PowerPC target, qemu correctly implements translation
    through the segment lookaside buffer.  Likewise it supports the
    slbmte instruction which is used to load entries into the SLB.
    
    However, it does not emulate the slbmfee and slbmfev instructions
    which read SLB entries back into registers.  Because these are
    only occasionally used in guests (mostly for debugging) we get
    away with it.
    
    However, given the recent SLB cleanups, it becomes quite easy to
    implement these, and thereby allow, amongst other things, a guest
    Linux to use xmon's command to dump the SLB.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 36ca342..f293f85 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -779,6 +779,8 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value);
 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
 target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
+int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt);
+int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt);
 #endif /* defined(TARGET_PPC64) */
 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
 #endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 452a35c..b9621d2 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -774,6 +774,32 @@ int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 
     return 0;
 }
+
+int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
+{
+    int slot = rb & 0xfff;
+    ppc_slb_t *slb = &env->slb[slot];
+
+    if (slot >= env->slb_nr) {
+        return -1;
+    }
+
+    *rt = slb->esid;
+    return 0;
+}
+
+int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
+{
+    int slot = rb & 0xfff;
+    ppc_slb_t *slb = &env->slb[slot];
+
+    if (slot >= env->slb_nr) {
+        return -1;
+    }
+
+    *rt = slb->vsid;
+    return 0;
+}
 #endif /* defined(TARGET_PPC64) */
 
 /* Perform segment based translation */
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index d512cb0..1a69cf8 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -341,6 +341,8 @@ DEF_HELPER_FLAGS_0(tlbia, TCG_CALL_CONST, void)
 DEF_HELPER_FLAGS_1(tlbie, TCG_CALL_CONST, void, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_2(store_slb, TCG_CALL_CONST, void, tl, tl)
+DEF_HELPER_1(load_slb_esid, tl, tl)
+DEF_HELPER_1(load_slb_vsid, tl, tl)
 DEF_HELPER_FLAGS_0(slbia, TCG_CALL_CONST, void)
 DEF_HELPER_FLAGS_1(slbie, TCG_CALL_CONST, void, tl)
 #endif
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index bf41627..bdb1f17 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3753,6 +3753,26 @@ void helper_store_slb (target_ulong rb, target_ulong rs)
     }
 }
 
+target_ulong helper_load_slb_esid (target_ulong rb)
+{
+    target_ulong rt;
+
+    if (ppc_load_slb_esid(env, rb, &rt) < 0) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
+    }
+    return rt;
+}
+
+target_ulong helper_load_slb_vsid (target_ulong rb)
+{
+    target_ulong rt;
+
+    if (ppc_load_slb_vsid(env, rb, &rt) < 0) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
+    }
+    return rt;
+}
+
 void helper_slbia (void)
 {
     ppc_slb_invalidate_all(env);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 49eab28..4252508 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4227,6 +4227,33 @@ static void gen_slbmte(DisasContext *ctx)
 #endif
 }
 
+static void gen_slbmfee(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+    if (unlikely(!ctx->mem_idx)) {
+        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+        return;
+    }
+    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
+                             cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
+
+static void gen_slbmfev(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+    if (unlikely(!ctx->mem_idx)) {
+        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+        return;
+    }
+    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
+                             cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
 #endif /* defined(TARGET_PPC64) */
 
 /***                      Lookaside buffer management                      ***/
@@ -8300,7 +8327,9 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
 GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
 GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
              PPC_SEGMENT_64B),
-GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B),
+GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
+GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
+GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
 #endif
 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
 GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
commit d569956eaff4be808419f1f259a5c388d8789db4
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:10 2011 +1100

    Add a hook to allow hypercalls to be emulated on PowerPC
    
    PowerPC and POWER chips since the POWER4 and 970 have a special
    hypervisor mode, and a corresponding form of the system call
    instruction which traps to the hypervisor.
    
    qemu currently has stub implementations of hypervisor mode.  That
    is, the outline is there to allow qemu to run a PowerPC hypervisor
    under emulation.  There are a number of details missing so this
    won't actually work at present, but the idea is there.
    
    What there is no provision at all, is for qemu to instead emulate
    the hypervisor itself.  That is to have hypercalls trap into qemu
    and their result be emulated from qemu, rather than running
    hypervisor code within the emulated system.
    
    Hypervisor hardware aware KVM implementations are in the works and
    it would  be useful for debugging and development to also allow
    full emulation of the same para-virtualized guests as such a KVM.
    
    Therefore, this patch adds a hook which will allow a machine to
    set up emulation of hypervisor calls.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 124bbbf..36ca342 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1646,4 +1646,6 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
 #endif
 }
 
+extern void (*cpu_ppc_hypercall)(CPUState *);
+
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 2094ca3..452a35c 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -70,6 +70,10 @@
 #  define LOG_EXCP(...) do { } while (0)
 #endif
 
+/*****************************************************************************/
+/* PowerPC Hypercall emulation */
+
+void (*cpu_ppc_hypercall)(CPUState *);
 
 /*****************************************************************************/
 /* PowerPC MMU emulation */
@@ -2152,6 +2156,10 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
     case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
         dump_syscall(env);
         lev = env->error_code;
+        if ((lev == 1) && cpu_ppc_hypercall) {
+            cpu_ppc_hypercall(env);
+            return;
+        }
         if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
             new_msr |= (target_ulong)MSR_HVB;
         goto store_next;
commit c48974903051ceb7cfbda23c22c159ea4b482d93
Author: David Gibson <dwg at au1.ibm.com>
Date:   Fri Apr 1 15:15:09 2011 +1100

    Allow qemu_devtree_setprop() to take arbitrary values
    
    Currently qemu_devtree_setprop() expects the new property value to be
    given as a uint32_t *.  While property values consisting of u32s are
    common, in general they can have any bytestring value.
    
    Therefore, this patch alters the function to take a void * instead,
    allowing callers to easily give anything as the property value.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/device_tree.c b/device_tree.c
index 426a631..21be070 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -74,7 +74,7 @@ fail:
 }
 
 int qemu_devtree_setprop(void *fdt, const char *node_path,
-                         const char *property, uint32_t *val_array, int size)
+                         const char *property, void *val_array, int size)
 {
     int offset;
 
diff --git a/device_tree.h b/device_tree.h
index f05c4e7..cecd98f 100644
--- a/device_tree.h
+++ b/device_tree.h
@@ -17,7 +17,7 @@
 void *load_device_tree(const char *filename_path, int *sizep);
 
 int qemu_devtree_setprop(void *fdt, const char *node_path,
-                         const char *property, uint32_t *val_array, int size);
+                         const char *property, void *val_array, int size);
 int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
                               const char *property, uint32_t val);
 int qemu_devtree_setprop_string(void *fdt, const char *node_path,
commit 81762d6dd0d430d87024f2c83e9c4dcc4329fb7d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Fri Apr 1 15:15:08 2011 +1100

    Clean up PowerPC SLB handling code
    
    Currently the SLB information when emulating a PowerPC 970 is
    storeed in a structure with the unhelpfully named fields 'tmp'
    and 'tmp64'.  While the layout in these fields does match the
    description of the SLB in the architecture document, it is not
    convenient either for looking up the SLB, or for emulating the
    slbmte instruction.
    
    This patch, therefore, reorganizes the SLB entry structure to be
    divided in the the "ESID related" and "VSID related" fields as
    they are divided in instructions accessing the SLB.
    
    In addition to making the code smaller and more readable, this will
    make it easier to implement for the 1TB segments used in more
    recent PowerPC chips.
    
    Signed-off-by: David Gibson <dwg at au1.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index deb8d7c..124bbbf 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -43,6 +43,8 @@
 # define TARGET_VIRT_ADDR_SPACE_BITS 64
 #endif
 
+#define TARGET_PAGE_BITS_16M 24
+
 #else /* defined (TARGET_PPC64) */
 /* PowerPC 32 definitions */
 #define TARGET_LONG_BITS 32
@@ -359,10 +361,31 @@ union ppc_tlb_t {
 
 typedef struct ppc_slb_t ppc_slb_t;
 struct ppc_slb_t {
-    uint64_t tmp64;
-    uint32_t tmp;
+    uint64_t esid;
+    uint64_t vsid;
 };
 
+/* Bits in the SLB ESID word */
+#define SLB_ESID_ESID           0xFFFFFFFFF0000000ULL
+#define SLB_ESID_V              0x0000000008000000ULL /* valid */
+
+/* Bits in the SLB VSID word */
+#define SLB_VSID_SHIFT          12
+#define SLB_VSID_SSIZE_SHIFT    62
+#define SLB_VSID_B              0xc000000000000000ULL
+#define SLB_VSID_B_256M         0x0000000000000000ULL
+#define SLB_VSID_VSID           0x3FFFFFFFFFFFF000ULL
+#define SLB_VSID_KS             0x0000000000000800ULL
+#define SLB_VSID_KP             0x0000000000000400ULL
+#define SLB_VSID_N              0x0000000000000200ULL /* no-execute */
+#define SLB_VSID_L              0x0000000000000100ULL
+#define SLB_VSID_C              0x0000000000000080ULL /* class */
+#define SLB_VSID_LP             0x0000000000000030ULL
+#define SLB_VSID_ATTR           0x0000000000000FFFULL
+
+#define SEGMENT_SHIFT_256M      28
+#define SEGMENT_MASK_256M       (~((1ULL << SEGMENT_SHIFT_256M) - 1))
+
 /*****************************************************************************/
 /* Machine state register bits definition                                    */
 #define MSR_SF   63 /* Sixty-four-bit mode                            hflags */
@@ -755,7 +778,7 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
 void ppc_store_asr (CPUPPCState *env, target_ulong value);
 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
 target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
-void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
+int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
 #endif /* defined(TARGET_PPC64) */
 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
 #endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 4b49101..2094ca3 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -672,85 +672,36 @@ static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
 }
 
 #if defined(TARGET_PPC64)
-static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
-{
-    ppc_slb_t *retval = &env->slb[nr];
-
-#if 0 // XXX implement bridge mode?
-    if (env->spr[SPR_ASR] & 1) {
-        target_phys_addr_t sr_base;
-
-        sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
-        sr_base += (12 * nr);
-
-        retval->tmp64 = ldq_phys(sr_base);
-        retval->tmp = ldl_phys(sr_base + 8);
-    }
-#endif
-
-    return retval;
-}
-
-static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
-{
-    ppc_slb_t *entry = &env->slb[nr];
-
-    if (slb == entry)
-        return;
-
-    entry->tmp64 = slb->tmp64;
-    entry->tmp = slb->tmp;
-}
-
-static inline int slb_is_valid(ppc_slb_t *slb)
-{
-    return (int)(slb->tmp64 & 0x0000000008000000ULL);
-}
-
-static inline void slb_invalidate(ppc_slb_t *slb)
-{
-    slb->tmp64 &= ~0x0000000008000000ULL;
-}
-
 static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
                              target_ulong *vsid, target_ulong *page_mask,
                              int *attr, int *target_page_bits)
 {
-    target_ulong mask;
-    int n, ret;
+    uint64_t esid;
+    int n;
 
-    ret = -5;
     LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
-    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
+
+    esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
+
     for (n = 0; n < env->slb_nr; n++) {
-        ppc_slb_t *slb = slb_get_entry(env, n);
-
-        LOG_SLB("%s: seg %d %016" PRIx64 " %08"
-                    PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
-        if (slb_is_valid(slb)) {
-            /* SLB entry is valid */
-            mask = 0xFFFFFFFFF0000000ULL;
-            if (slb->tmp & 0x8) {
-                /* 16 MB PTEs */
-                if (target_page_bits)
-                    *target_page_bits = 24;
-            } else {
-                /* 4 KB PTEs */
-                if (target_page_bits)
-                    *target_page_bits = TARGET_PAGE_BITS;
-            }
-            if ((eaddr & mask) == (slb->tmp64 & mask)) {
-                /* SLB match */
-                *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
-                *page_mask = ~mask;
-                *attr = slb->tmp & 0xFF;
-                ret = n;
-                break;
+        ppc_slb_t *slb = &env->slb[n];
+
+        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
+                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
+        if (slb->esid == esid) {
+            *vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+            *page_mask = ~SEGMENT_MASK_256M;
+            *attr = slb->vsid & SLB_VSID_ATTR;
+            if (target_page_bits) {
+                *target_page_bits = (slb->vsid & SLB_VSID_L)
+                    ? TARGET_PAGE_BITS_16M
+                    : TARGET_PAGE_BITS;
             }
+            return n;
         }
     }
 
-    return ret;
+    return -5;
 }
 
 void ppc_slb_invalidate_all (CPUPPCState *env)
@@ -760,11 +711,10 @@ void ppc_slb_invalidate_all (CPUPPCState *env)
     do_invalidate = 0;
     /* XXX: Warning: slbia never invalidates the first segment */
     for (n = 1; n < env->slb_nr; n++) {
-        ppc_slb_t *slb = slb_get_entry(env, n);
+        ppc_slb_t *slb = &env->slb[n];
 
-        if (slb_is_valid(slb)) {
-            slb_invalidate(slb);
-            slb_set_entry(env, n, slb);
+        if (slb->esid & SLB_ESID_V) {
+            slb->esid &= ~SLB_ESID_V;
             /* XXX: given the fact that segment size is 256 MB or 1TB,
              *      and we still don't have a tlb_flush_mask(env, n, mask)
              *      in Qemu, we just invalidate all TLBs
@@ -781,68 +731,44 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
     target_ulong vsid, page_mask;
     int attr;
     int n;
+    ppc_slb_t *slb;
 
     n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
-    if (n >= 0) {
-        ppc_slb_t *slb = slb_get_entry(env, n);
-
-        if (slb_is_valid(slb)) {
-            slb_invalidate(slb);
-            slb_set_entry(env, n, slb);
-            /* XXX: given the fact that segment size is 256 MB or 1TB,
-             *      and we still don't have a tlb_flush_mask(env, n, mask)
-             *      in Qemu, we just invalidate all TLBs
-             */
-            tlb_flush(env, 1);
-        }
+    if (n < 0) {
+        return;
     }
-}
 
-target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
-{
-    target_ulong rt;
-    ppc_slb_t *slb = slb_get_entry(env, slb_nr);
+    slb = &env->slb[n];
 
-    if (slb_is_valid(slb)) {
-        /* SLB entry is valid */
-        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
-        rt = slb->tmp >> 8;             /* 65:88 => 40:63 */
-        rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
-        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
-        rt |= ((slb->tmp >> 4) & 0xF) << 27;
-    } else {
-        rt = 0;
-    }
-    LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
-            TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
+    if (slb->esid & SLB_ESID_V) {
+        slb->esid &= ~SLB_ESID_V;
 
-    return rt;
+        /* XXX: given the fact that segment size is 256 MB or 1TB,
+         *      and we still don't have a tlb_flush_mask(env, n, mask)
+         *      in Qemu, we just invalidate all TLBs
+         */
+        tlb_flush(env, 1);
+    }
 }
 
-void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
+int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 {
-    ppc_slb_t *slb;
-
-    uint64_t vsid;
-    uint64_t esid;
-    int flags, valid, slb_nr;
-
-    vsid = rs >> 12;
-    flags = ((rs >> 8) & 0xf);
+    int slot = rb & 0xfff;
+    uint64_t esid = rb & ~0xfff;
+    ppc_slb_t *slb = &env->slb[slot];
 
-    esid = rb >> 28;
-    valid = (rb & (1 << 27));
-    slb_nr = rb & 0xfff;
+    if (slot >= env->slb_nr) {
+        return -1;
+    }
 
-    slb = slb_get_entry(env, slb_nr);
-    slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
-    slb->tmp = (vsid << 8) | (flags << 3);
+    slb->esid = esid;
+    slb->vsid = rs;
 
     LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
-            " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
-            slb->tmp);
+            " %016" PRIx64 "\n", __func__, slot, rb, rs,
+            slb->esid, slb->vsid);
 
-    slb_set_entry(env, slb_nr, slb);
+    return 0;
 }
 #endif /* defined(TARGET_PPC64) */
 
@@ -860,24 +786,22 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
 {
     target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
     target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
-#if defined(TARGET_PPC64)
-    int attr;
-#endif
     int ds, vsid_sh, sdr_sh, pr, target_page_bits;
     int ret, ret2;
 
     pr = msr_pr;
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64) {
+        int attr;
+
         LOG_MMU("Check SLBs\n");
         ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
                          &target_page_bits);
         if (ret < 0)
             return ret;
-        ctx->key = ((attr & 0x40) && (pr != 0)) ||
-            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
+        ctx->key = !!(pr ? (attr & SLB_VSID_KP) : (attr & SLB_VSID_KS));
         ds = 0;
-        ctx->nx = attr & 0x10 ? 1 : 0;
+        ctx->nx = !!(attr & SLB_VSID_N);
         ctx->eaddr = eaddr;
         vsid_mask = 0x00003FFFFFFFFF80ULL;
         vsid_sh = 7;
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 2bf9283..d512cb0 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -340,7 +340,6 @@ DEF_HELPER_1(74xx_tlbi, void, tl)
 DEF_HELPER_FLAGS_0(tlbia, TCG_CALL_CONST, void)
 DEF_HELPER_FLAGS_1(tlbie, TCG_CALL_CONST, void, tl)
 #if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_1(load_slb, TCG_CALL_CONST, tl, tl)
 DEF_HELPER_FLAGS_2(store_slb, TCG_CALL_CONST, void, tl, tl)
 DEF_HELPER_FLAGS_0(slbia, TCG_CALL_CONST, void)
 DEF_HELPER_FLAGS_1(slbie, TCG_CALL_CONST, void, tl)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 17e070a..bf41627 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3746,14 +3746,11 @@ void helper_store_sr (target_ulong sr_num, target_ulong val)
 
 /* SLB management */
 #if defined(TARGET_PPC64)
-target_ulong helper_load_slb (target_ulong slb_nr)
-{
-    return ppc_load_slb(env, slb_nr);
-}
-
 void helper_store_slb (target_ulong rb, target_ulong rs)
 {
-    ppc_store_slb(env, rb, rs);
+    if (ppc_store_slb(env, rb, rs) < 0) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
+    }
 }
 
 void helper_slbia (void)
commit 17d9b3af5b7f93e43d7fbdcb6f14cad54de9f1ae
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 22 07:41:29 2011 +0100

    target-ppc: ext32u instead of andi with constant
    
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3d265e3..49eab28 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6975,7 +6975,7 @@ static inline void gen_evmergelo(DisasContext *ctx)
 #if defined(TARGET_PPC64)
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
-    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
+    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
     tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
     tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
     tcg_temp_free(t0);
@@ -6994,7 +6994,7 @@ static inline void gen_evmergehilo(DisasContext *ctx)
 #if defined(TARGET_PPC64)
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
-    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
+    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
     tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
     tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
     tcg_temp_free(t0);
@@ -7083,14 +7083,14 @@ static inline void gen_evsel(DisasContext *ctx)
     tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
     tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
 #if defined(TARGET_PPC64)
-    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
+    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
 #else
     tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
 #endif
     tcg_gen_br(l4);
     gen_set_label(l3);
 #if defined(TARGET_PPC64)
-    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
+    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
 #else
     tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
 #endif
commit a5086f95421e43c7b9e1b28a111aae0be4848117
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:01:04 2011 +0100

    lm32: use lookup table for opcodes
    
    Instead of a for loop use a faster lookup table.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/lm32-decode.h b/target-lm32/lm32-decode.h
deleted file mode 100644
index 42205d9..0000000
--- a/target-lm32/lm32-decode.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *  LatticeMico32 instruction decoding macros.
- *
- *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Convenient binary macros */
-#define HEX__(n) 0x##n##LU
-#define B8__(x) (((x&0x0000000FLU) ? 1 : 0) \
-                  + ((x&0x000000F0LU) ? 2 : 0) \
-                  + ((x&0x00000F00LU) ? 4 : 0) \
-                  + ((x&0x0000F000LU) ? 8 : 0) \
-                  + ((x&0x000F0000LU) ? 16 : 0) \
-                  + ((x&0x00F00000LU) ? 32 : 0) \
-                  + ((x&0x0F000000LU) ? 64 : 0) \
-                  + ((x&0xF0000000LU) ? 128 : 0))
-#define B8(d) ((unsigned char)B8__(HEX__(d)))
-
-/* Decode logic, value and mask.  */
-#define DEC_ADD     {B8(00001101), B8(00011111)}
-#define DEC_AND     {B8(00001000), B8(00011111)}
-#define DEC_ANDHI   {B8(00011000), B8(00111111)}
-#define DEC_B       {B8(00110000), B8(00111111)}
-#define DEC_BI      {B8(00111000), B8(00111111)}
-#define DEC_BE      {B8(00010001), B8(00111111)}
-#define DEC_BG      {B8(00010010), B8(00111111)}
-#define DEC_BGE     {B8(00010011), B8(00111111)}
-#define DEC_BGEU    {B8(00010100), B8(00111111)}
-#define DEC_BGU     {B8(00010101), B8(00111111)}
-#define DEC_BNE     {B8(00010111), B8(00111111)}
-#define DEC_CALL    {B8(00110110), B8(00111111)}
-#define DEC_CALLI   {B8(00111110), B8(00111111)}
-#define DEC_CMPE    {B8(00011001), B8(00011111)}
-#define DEC_CMPG    {B8(00011010), B8(00011111)}
-#define DEC_CMPGE   {B8(00011011), B8(00011111)}
-#define DEC_CMPGEU  {B8(00011100), B8(00011111)}
-#define DEC_CMPGU   {B8(00011101), B8(00011111)}
-#define DEC_CMPNE   {B8(00011111), B8(00011111)}
-#define DEC_DIVU    {B8(00100011), B8(00111111)}
-#define DEC_LB      {B8(00000100), B8(00111111)}
-#define DEC_LBU     {B8(00010000), B8(00111111)}
-#define DEC_LH      {B8(00000111), B8(00111111)}
-#define DEC_LHU     {B8(00001011), B8(00111111)}
-#define DEC_LW      {B8(00001010), B8(00111111)}
-#define DEC_MODU    {B8(00110001), B8(00111111)}
-#define DEC_MUL     {B8(00000010), B8(00011111)}
-#define DEC_NOR     {B8(00000001), B8(00011111)}
-#define DEC_OR      {B8(00001110), B8(00011111)}
-#define DEC_ORHI    {B8(00011110), B8(00111111)}
-#define DEC_SCALL   {B8(00101011), B8(00111111)}
-#define DEC_RCSR    {B8(00100100), B8(00111111)}
-#define DEC_SB      {B8(00001100), B8(00111111)}
-#define DEC_SEXTB   {B8(00101100), B8(00111111)}
-#define DEC_SEXTH   {B8(00110111), B8(00111111)}
-#define DEC_SH      {B8(00000011), B8(00111111)}
-#define DEC_SL      {B8(00001111), B8(00011111)}
-#define DEC_SR      {B8(00000101), B8(00011111)}
-#define DEC_SRU     {B8(00000000), B8(00011111)}
-#define DEC_SUB     {B8(00110010), B8(00111111)}
-#define DEC_SW      {B8(00010110), B8(00111111)}
-#define DEC_USER    {B8(00110011), B8(00111111)}
-#define DEC_WCSR    {B8(00110100), B8(00111111)}
-#define DEC_XNOR    {B8(00001001), B8(00011111)}
-#define DEC_XOR     {B8(00000110), B8(00011111)}
-
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index aa08a14..666d5f4 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -29,7 +29,6 @@
 #include "disas.h"
 #include "helper.h"
 #include "tcg-op.h"
-#include "lm32-decode.h"
 #include "qemu-common.h"
 
 #include "hw/lm32_pic.h"
@@ -963,66 +962,28 @@ static void dec_xor(DisasContext *dc)
     }
 }
 
-typedef struct {
-    struct {
-        uint32_t bits;
-        uint32_t mask;
-    };
-    void (*dec)(DisasContext *dc);
-} DecoderInfo;
+static void dec_ill(DisasContext *dc)
+{
+    cpu_abort(dc->env, "unknown opcode 0x%02x\n", dc->opcode);
+}
 
+typedef void (*DecoderInfo)(DisasContext *dc);
 static const DecoderInfo decinfo[] = {
-    {DEC_ADD, dec_add},
-    {DEC_AND, dec_and},
-    {DEC_ANDHI, dec_andhi},
-    {DEC_B, dec_b},
-    {DEC_BI, dec_bi},
-    {DEC_BE, dec_be},
-    {DEC_BG, dec_bg},
-    {DEC_BGE, dec_bge},
-    {DEC_BGEU, dec_bgeu},
-    {DEC_BGU, dec_bgu},
-    {DEC_BNE, dec_bne},
-    {DEC_CALL, dec_call},
-    {DEC_CALLI, dec_calli},
-    {DEC_CMPE, dec_cmpe},
-    {DEC_CMPG, dec_cmpg},
-    {DEC_CMPGE, dec_cmpge},
-    {DEC_CMPGEU, dec_cmpgeu},
-    {DEC_CMPGU, dec_cmpgu},
-    {DEC_CMPNE, dec_cmpne},
-    {DEC_DIVU, dec_divu},
-    {DEC_LB, dec_lb},
-    {DEC_LBU, dec_lbu},
-    {DEC_LH, dec_lh},
-    {DEC_LHU, dec_lhu},
-    {DEC_LW, dec_lw},
-    {DEC_MODU, dec_modu},
-    {DEC_MUL, dec_mul},
-    {DEC_NOR, dec_nor},
-    {DEC_OR, dec_or},
-    {DEC_ORHI, dec_orhi},
-    {DEC_SCALL, dec_scall},
-    {DEC_RCSR, dec_rcsr},
-    {DEC_SB, dec_sb},
-    {DEC_SEXTB, dec_sextb},
-    {DEC_SEXTH, dec_sexth},
-    {DEC_SH, dec_sh},
-    {DEC_SL, dec_sl},
-    {DEC_SR, dec_sr},
-    {DEC_SRU, dec_sru},
-    {DEC_SUB, dec_sub},
-    {DEC_SW, dec_sw},
-    {DEC_USER, dec_user},
-    {DEC_WCSR, dec_wcsr},
-    {DEC_XNOR, dec_xnor},
-    {DEC_XOR, dec_xor},
+    dec_sru, dec_nor, dec_mul, dec_sh, dec_lb, dec_sr, dec_xor, dec_lh,
+    dec_and, dec_xnor, dec_lw, dec_lhu, dec_sb, dec_add, dec_or, dec_sl,
+    dec_lbu, dec_be, dec_bg, dec_bge, dec_bgeu, dec_bgu, dec_sw, dec_bne,
+    dec_andhi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_orhi,
+    dec_cmpne,
+    dec_sru, dec_nor, dec_mul, dec_divu, dec_rcsr, dec_sr, dec_xor, dec_ill,
+    dec_and, dec_xnor, dec_ill, dec_scall, dec_sextb, dec_add, dec_or, dec_sl,
+    dec_b, dec_modu, dec_sub, dec_user, dec_wcsr, dec_ill, dec_call, dec_sexth,
+    dec_bi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_calli,
+    dec_cmpne
 };
 
 static inline void decode(DisasContext *dc)
 {
     uint32_t ir;
-    int i;
 
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
         tcg_gen_debug_insn_start(dc->pc);
@@ -1061,15 +1022,10 @@ static inline void decode(DisasContext *dc)
         dc->format = OP_FMT_RI;
     }
 
-    /* Large switch for all insns.  */
-    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
-        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
-            decinfo[i].dec(dc);
-            return;
-        }
-    }
+    assert(ARRAY_SIZE(decinfo) == 64);
+    assert(dc->opcode < 64);
 
-    cpu_abort(dc->env, "unknown opcode 0x%02x\n", dc->opcode);
+    decinfo[dc->opcode](dc);
 }
 
 static void check_breakpoint(CPUState *env, DisasContext *dc)
commit fcda98630b121a63c9de0705df02e59f4dc2fecc
Author: Michael Walle <michael at walle.cc>
Date:   Mon Mar 7 23:00:13 2011 +0100

    lm32: rename raise opcode to scall
    
    To be consistent with the new reference manual.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/lm32-decode.h b/target-lm32/lm32-decode.h
index f745b39..42205d9 100644
--- a/target-lm32/lm32-decode.h
+++ b/target-lm32/lm32-decode.h
@@ -60,7 +60,7 @@
 #define DEC_NOR     {B8(00000001), B8(00011111)}
 #define DEC_OR      {B8(00001110), B8(00011111)}
 #define DEC_ORHI    {B8(00011110), B8(00111111)}
-#define DEC_RAISE   {B8(00101011), B8(00111111)}
+#define DEC_SCALL   {B8(00101011), B8(00111111)}
 #define DEC_RCSR    {B8(00100100), B8(00111111)}
 #define DEC_SB      {B8(00001100), B8(00111111)}
 #define DEC_SEXTB   {B8(00101100), B8(00111111)}
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 0b0e405..aa08a14 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -583,7 +583,7 @@ static void dec_orhi(DisasContext *dc)
     tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
 }
 
-static void dec_raise(DisasContext *dc)
+static void dec_scall(DisasContext *dc)
 {
     TCGv t0;
     int l1;
@@ -1002,7 +1002,7 @@ static const DecoderInfo decinfo[] = {
     {DEC_NOR, dec_nor},
     {DEC_OR, dec_or},
     {DEC_ORHI, dec_orhi},
-    {DEC_RAISE, dec_raise},
+    {DEC_SCALL, dec_scall},
     {DEC_RCSR, dec_rcsr},
     {DEC_SB, dec_sb},
     {DEC_SEXTB, dec_sextb},
commit 4d54ec7898bd951007cb6122d5315584bd41d0c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 9 18:21:10 2011 +0100

    add a service to reap zombies, use it in SLIRP
    
    SLIRP -smb support wants to fork a process and forget about reaping it.
    To please it, add a generic service to register a process id and let
    QEMU reap it.  In the future it could be enhanced to pass a status,
    but this would be unused.
    
    With this in place, the SIGCHLD signal handler would not stomp on pclose
    anymore.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/iohandler.c b/iohandler.c
index 2e30fe3..2b82421 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -27,6 +27,10 @@
 #include "qemu-char.h"
 #include "qemu-queue.h"
 
+#ifndef _WIN32
+#include <sys/wait.h>
+#endif
+
 typedef struct IOHandlerRecord {
     int fd;
     IOCanReadHandler *fd_read_poll;
@@ -127,3 +131,63 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int re
         }
     }
 }
+
+/* reaping of zombies.  right now we're not passing the status to
+   anyone, but it would be possible to add a callback.  */
+#ifndef _WIN32
+typedef struct ChildProcessRecord {
+    int pid;
+    QLIST_ENTRY(ChildProcessRecord) next;
+} ChildProcessRecord;
+
+static QLIST_HEAD(, ChildProcessRecord) child_watches =
+    QLIST_HEAD_INITIALIZER(child_watches);
+
+static QEMUBH *sigchld_bh;
+
+static void sigchld_handler(int signal)
+{
+    qemu_bh_schedule(sigchld_bh);
+}
+
+static void sigchld_bh_handler(void *opaque)
+{
+    ChildProcessRecord *rec, *next;
+
+    QLIST_FOREACH_SAFE(rec, &child_watches, next, next) {
+        if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) {
+            QLIST_REMOVE(rec, next);
+            qemu_free(rec);
+        }
+    }
+}
+
+static void qemu_init_child_watch(void)
+{
+    struct sigaction act;
+    sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
+
+    act.sa_handler = sigchld_handler;
+    act.sa_flags = SA_NOCLDSTOP;
+    sigaction(SIGCHLD, &act, NULL);
+}
+
+int qemu_add_child_watch(pid_t pid)
+{
+    ChildProcessRecord *rec;
+
+    if (!sigchld_bh) {
+        qemu_init_child_watch();
+    }
+
+    QLIST_FOREACH(rec, &child_watches, next) {
+        if (rec->pid == pid) {
+            return 1;
+        }
+    }
+    rec = qemu_mallocz(sizeof(ChildProcessRecord));
+    rec->pid = pid;
+    QLIST_INSERT_HEAD(&child_watches, rec, next);
+    return 0;
+}
+#endif
diff --git a/os-posix.c b/os-posix.c
index eb49e2f..3204197 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -67,11 +67,6 @@ static void termsig_handler(int signal, siginfo_t *info, void *c)
     qemu_system_killed(info->si_signo, info->si_pid);
 }
 
-static void sigchld_handler(int signal)
-{
-    waitpid(-1, NULL, WNOHANG);
-}
-
 void os_setup_signal_handling(void)
 {
     struct sigaction act;
@@ -82,10 +77,6 @@ void os_setup_signal_handling(void)
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGHUP,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
-
-    act.sa_handler = sigchld_handler;
-    act.sa_flags = SA_NOCLDSTOP;
-    sigaction(SIGCHLD, &act, NULL);
 }
 
 /* Find a likely location for support files using the location of the binary.
diff --git a/qemu-common.h b/qemu-common.h
index 665c893..8ecb488 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -214,6 +214,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
 void qemu_set_cloexec(int fd);
 
 #ifndef _WIN32
+int qemu_add_child_watch(pid_t pid);
 int qemu_eventfd(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 #endif
diff --git a/slirp/misc.c b/slirp/misc.c
index 19dbec4..08eba6a 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -119,6 +119,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 	char *bptr;
 	const char *curarg;
 	int c, i, ret;
+	pid_t pid;
 
 	DEBUG_CALL("fork_exec");
 	DEBUG_ARG("so = %lx", (long)so);
@@ -142,7 +143,8 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 		}
 	}
 
-	switch(fork()) {
+	pid = fork();
+	switch(pid) {
 	 case -1:
 		lprint("Error: fork failed: %s\n", strerror(errno));
 		close(s);
@@ -206,6 +208,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 		exit(1);
 
 	 default:
+		qemu_add_child_watch(pid);
 		if (do_pty == 2) {
 			close(s);
 			so->s = master;
commit 0298141998ea3e19fd86b5a7122aab2fd1ebad51
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 9 18:21:09 2011 +0100

    extract I/O handler lists to iohandler.c
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index f8cf199..42301fd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -98,7 +98,7 @@ common-obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
 common-obj-y += qemu-char.o savevm.o #aio.o
 common-obj-y += msmouse.o ps2.o
 common-obj-y += qdev.o qdev-properties.o
-common-obj-y += block-migration.o
+common-obj-y += block-migration.o iohandler.o
 common-obj-y += pflib.o
 common-obj-y += bitmap.o bitops.o
 
diff --git a/iohandler.c b/iohandler.c
new file mode 100644
index 0000000..2e30fe3
--- /dev/null
+++ b/iohandler.c
@@ -0,0 +1,129 @@
+/*
+ * QEMU System Emulator - managing I/O handler
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "config-host.h"
+#include "qemu-common.h"
+#include "qemu-char.h"
+#include "qemu-queue.h"
+
+typedef struct IOHandlerRecord {
+    int fd;
+    IOCanReadHandler *fd_read_poll;
+    IOHandler *fd_read;
+    IOHandler *fd_write;
+    int deleted;
+    void *opaque;
+    QLIST_ENTRY(IOHandlerRecord) next;
+} IOHandlerRecord;
+
+static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+    QLIST_HEAD_INITIALIZER(io_handlers);
+
+
+/* XXX: fd_read_poll should be suppressed, but an API change is
+   necessary in the character devices to suppress fd_can_read(). */
+int qemu_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque)
+{
+    IOHandlerRecord *ioh;
+
+    if (!fd_read && !fd_write) {
+        QLIST_FOREACH(ioh, &io_handlers, next) {
+            if (ioh->fd == fd) {
+                ioh->deleted = 1;
+                break;
+            }
+        }
+    } else {
+        QLIST_FOREACH(ioh, &io_handlers, next) {
+            if (ioh->fd == fd)
+                goto found;
+        }
+        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
+        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+    found:
+        ioh->fd = fd;
+        ioh->fd_read_poll = fd_read_poll;
+        ioh->fd_read = fd_read;
+        ioh->fd_write = fd_write;
+        ioh->opaque = opaque;
+        ioh->deleted = 0;
+    }
+    return 0;
+}
+
+int qemu_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque)
+{
+    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
+}
+
+void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds)
+{
+    IOHandlerRecord *ioh;
+
+    QLIST_FOREACH(ioh, &io_handlers, next) {
+        if (ioh->deleted)
+            continue;
+        if (ioh->fd_read &&
+            (!ioh->fd_read_poll ||
+             ioh->fd_read_poll(ioh->opaque) != 0)) {
+            FD_SET(ioh->fd, readfds);
+            if (ioh->fd > *pnfds)
+                *pnfds = ioh->fd;
+        }
+        if (ioh->fd_write) {
+            FD_SET(ioh->fd, writefds);
+            if (ioh->fd > *pnfds)
+                *pnfds = ioh->fd;
+        }
+    }
+}
+
+void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret)
+{
+    if (ret > 0) {
+        IOHandlerRecord *pioh, *ioh;
+
+        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
+            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
+                ioh->fd_read(ioh->opaque);
+            }
+            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
+                ioh->fd_write(ioh->opaque);
+            }
+
+            /* Do this last in case read/write handlers marked it for deletion */
+            if (ioh->deleted) {
+                QLIST_REMOVE(ioh, next);
+                qemu_free(ioh);
+            }
+        }
+    }
+}
diff --git a/qemu-common.h b/qemu-common.h
index 7a96dd1..665c893 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -227,6 +227,9 @@ typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
 typedef int IOCanReadHandler(void *opaque);
 typedef void IOHandler(void *opaque);
 
+void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
+void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
+
 struct ParallelIOArg {
     void *buffer;
     int count;
diff --git a/vl.c b/vl.c
index 192a240..d3d81e0 100644
--- a/vl.c
+++ b/vl.c
@@ -1023,68 +1023,6 @@ void pcmcia_info(Monitor *mon)
 }
 
 /***********************************************************/
-/* I/O handling */
-
-typedef struct IOHandlerRecord {
-    int fd;
-    IOCanReadHandler *fd_read_poll;
-    IOHandler *fd_read;
-    IOHandler *fd_write;
-    int deleted;
-    void *opaque;
-    /* temporary data */
-    struct pollfd *ufd;
-    QLIST_ENTRY(IOHandlerRecord) next;
-} IOHandlerRecord;
-
-static QLIST_HEAD(, IOHandlerRecord) io_handlers =
-    QLIST_HEAD_INITIALIZER(io_handlers);
-
-
-/* XXX: fd_read_poll should be suppressed, but an API change is
-   necessary in the character devices to suppress fd_can_read(). */
-int qemu_set_fd_handler2(int fd,
-                         IOCanReadHandler *fd_read_poll,
-                         IOHandler *fd_read,
-                         IOHandler *fd_write,
-                         void *opaque)
-{
-    IOHandlerRecord *ioh;
-
-    if (!fd_read && !fd_write) {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
-            if (ioh->fd == fd) {
-                ioh->deleted = 1;
-                break;
-            }
-        }
-    } else {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
-            if (ioh->fd == fd)
-                goto found;
-        }
-        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
-        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
-    found:
-        ioh->fd = fd;
-        ioh->fd_read_poll = fd_read_poll;
-        ioh->fd_read = fd_read;
-        ioh->fd_write = fd_write;
-        ioh->opaque = opaque;
-        ioh->deleted = 0;
-    }
-    return 0;
-}
-
-int qemu_set_fd_handler(int fd,
-                        IOHandler *fd_read,
-                        IOHandler *fd_write,
-                        void *opaque)
-{
-    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
-}
-
-/***********************************************************/
 /* machine registration */
 
 static QEMUMachine *first_machine = NULL;
@@ -1343,7 +1281,6 @@ void qemu_system_vmstop_request(int reason)
 
 void main_loop_wait(int nonblocking)
 {
-    IOHandlerRecord *ioh;
     fd_set rfds, wfds, xfds;
     int ret, nfds;
     struct timeval tv;
@@ -1358,56 +1295,23 @@ void main_loop_wait(int nonblocking)
 
     os_host_main_loop_wait(&timeout);
 
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
     FD_ZERO(&rfds);
     FD_ZERO(&wfds);
     FD_ZERO(&xfds);
-    QLIST_FOREACH(ioh, &io_handlers, next) {
-        if (ioh->deleted)
-            continue;
-        if (ioh->fd_read &&
-            (!ioh->fd_read_poll ||
-             ioh->fd_read_poll(ioh->opaque) != 0)) {
-            FD_SET(ioh->fd, &rfds);
-            if (ioh->fd > nfds)
-                nfds = ioh->fd;
-        }
-        if (ioh->fd_write) {
-            FD_SET(ioh->fd, &wfds);
-            if (ioh->fd > nfds)
-                nfds = ioh->fd;
-        }
-    }
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
+    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
     slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
 
     qemu_mutex_unlock_iothread();
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
     qemu_mutex_lock_iothread();
-    if (ret > 0) {
-        IOHandlerRecord *pioh;
-
-        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
-            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
-                ioh->fd_read(ioh->opaque);
-            }
-            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
-                ioh->fd_write(ioh->opaque);
-            }
-
-            /* Do this last in case read/write handlers marked it for deletion */
-            if (ioh->deleted) {
-                QLIST_REMOVE(ioh, next);
-                qemu_free(ioh);
-            }
-        }
-    }
 
+    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
     slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
 
     qemu_run_all_timers();
commit 7b67b18adf921c77aa8443f3b4cddab87908ee1e
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Mar 16 12:09:09 2011 +0200

    vhost: fix dirty page handling
    
    vhost was passing a physical address to cpu_physical_memory_set_dirty,
    which is wrong: we need to translate to ram address first.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    Note: this lead to crashes during migration, so the patch
    is needed on the stable branch too.

diff --git a/hw/vhost.c b/hw/vhost.c
index 0ca3507..14b571d 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -47,8 +47,10 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
         log = __sync_fetch_and_and(from, 0);
         while ((bit = sizeof(log) > sizeof(int) ?
                 ffsll(log) : ffs(log))) {
+            ram_addr_t ram_addr;
             bit -= 1;
-            cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
+            ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE);
+            cpu_physical_memory_set_dirty(ram_addr);
             log &= ~(0x1ull << bit);
         }
         addr += VHOST_LOG_CHUNK;
commit fbe0c5591077814eead05217fc96f087b254a6a8
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Mar 22 18:32:50 2011 +0200

    virtio-serial: don't crash on invalid input
    
    Fix crash on invalid input in virtio-serial.
    Discovered by code review, untested.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index a82fbe9..6227379 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -594,6 +594,9 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
         id = qemu_get_be32(f);
         port = find_port_by_id(s, id);
+        if (!port) {
+            return -EINVAL;
+        }
 
         port->guest_connected = qemu_get_byte(f);
         host_connected = qemu_get_byte(f);
commit 6cdfab2868dd593902e2b7db3ba9f49f2cc03e3f
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Mar 27 13:37:35 2011 +0200

    e1000: check buffer availability
    
    Reduce spurious packet drops on RX ring empty
    by verifying that we have at least 1 buffer
    ahead of the time.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 2a4d5c7..55daae0 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -625,14 +625,6 @@ e1000_set_link_status(VLANClientState *nc)
         set_ics(s, 0, E1000_ICR_LSC);
 }
 
-static int
-e1000_can_receive(VLANClientState *nc)
-{
-    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
-
-    return (s->mac_reg[RCTL] & E1000_RCTL_EN);
-}
-
 static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
 {
     int bufs;
@@ -651,6 +643,14 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
     return total_size <= bufs * s->rxbuf_size;
 }
 
+static int
+e1000_can_receive(VLANClientState *nc)
+{
+    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    return (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+}
+
 static ssize_t
 e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
commit 89c473fd82daf7dddad8162a683bcd0ef671ecda
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sat Mar 19 19:28:19 2011 +0200

    virtio-pci: fix bus master work around on load
    
    Commit c81131db15dd1844d0db1d51f3cd7a105cfd2cf3
    detects old guests by comparing virtio and
    PCI status. It attempts to do this on load,
    as well, but load_config callback in a binding
    is invoked too early and so the virtio status
    isn't set yet.
    
    We could add yet another callback to the
    binding, to invoke after load, but it
    seems easier to reuse the existing vmstate
    callback.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Cc: Alexander Graf <agraf at suse.de>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ef65590..df10703 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -160,13 +160,6 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
     if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
         return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
     }
-
-    /* Try to find out if the guest has bus master disabled, but is
-       in ready state. Then we have a buggy guest OS. */
-    if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
-        !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
-        proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
-    }
     return 0;
 }
 
@@ -651,6 +644,12 @@ static void virtio_pci_vmstate_change(void *opaque, bool running)
     VirtIOPCIProxy *proxy = opaque;
 
     if (running) {
+        /* Try to find out if the guest has bus master disabled, but is
+           in ready state. Then we have a buggy guest OS. */
+        if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
+        }
         virtio_pci_start_ioeventfd(proxy);
     } else {
         virtio_pci_stop_ioeventfd(proxy);
diff --git a/hw/virtio.h b/hw/virtio.h
index d0920a8..bc72289 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -92,6 +92,7 @@ typedef struct {
     void (*save_queue)(void * opaque, int n, QEMUFile *f);
     int (*load_config)(void * opaque, QEMUFile *f);
     int (*load_queue)(void * opaque, int n, QEMUFile *f);
+    int (*load_done)(void * opaque, QEMUFile *f);
     unsigned (*get_features)(void * opaque);
     bool (*query_guest_notifiers)(void * opaque);
     int (*set_guest_notifiers)(void * opaque, bool assigned);
commit 6f3279b5d1d39e658d29d20221f5a5de850b0c15
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu Jan 27 15:56:39 2011 +0900

    pci: use uint8_t for devfn_min
    
    use uint8_t for devfn_min instead of int.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index df184f1..6b577e1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -256,7 +256,7 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, int devfn_min)
+                         const char *name, uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
@@ -269,7 +269,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
 {
     PCIBus *bus;
 
@@ -303,7 +303,7 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, int devfn_min, int nirq)
+                         void *irq_opaque, uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
diff --git a/hw/pci.h b/hw/pci.h
index 14aba97..52ee8c9 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -230,14 +230,14 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, int devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min);
+                         const char *name, uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, int devfn_min, int nirq);
+                         void *irq_opaque, uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index efaefcd..fbe1866 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -16,7 +16,7 @@ extern struct BusInfo pci_bus_info;
 
 struct PCIBus {
     BusState qbus;
-    int devfn_min;
+    uint8_t devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
     pci_hotplug_fn hotplug;
commit 6ff534b678e26450ad6e2ad850b70c9db0e92139
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu Jan 27 15:56:38 2011 +0900

    pci: use PCI_DEVFN in pci_get_bus_devfn()
    
    Replace hardcoded logic by a common macro.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 44a1f9e..df184f1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -558,7 +558,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
         return NULL;
     }
 
-    *devfnp = slot << 3;
+    *devfnp = PCI_DEVFN(slot, 0);
     return pci_find_bus(pci_find_root_bus(dom), bus);
 }
 
commit 5256d8bfad9b0113dc2f9b57706eaad26b008987
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu Jan 27 15:56:36 2011 +0900

    pci: use devfn for pci_find_device() instead of (slot, fn) pair
    
    (slot, fn) pair is somewhat confusing because of ARI.
    So use devfn for pci_find_device() instead of (slot, fn).
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 478fe9b..b59be2a 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -127,7 +127,8 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
         }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus, slot, 0);
+        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
+                              PCI_DEVFN(slot, 0));
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -277,7 +278,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
         return -1;
     }
 
-    d = pci_find_device(pci_find_root_bus(dom), bus, slot, 0);
+    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
     if (!d) {
         monitor_printf(mon, "slot %d empty\n", slot);
         return -1;
diff --git a/hw/pci.c b/hw/pci.c
index 8b76cea..44a1f9e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1603,14 +1603,14 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
     return NULL;
 }
 
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
 {
     bus = pci_find_bus(bus, bus_num);
 
     if (!bus)
         return NULL;
 
-    return bus->devices[PCI_DEVFN(slot, function)];
+    return bus->devices[devfn];
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/pci.h b/hw/pci.h
index 7d56337..14aba97 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -252,7 +252,7 @@ void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDe
 PCIBus *pci_find_root_bus(int domain);
 int pci_find_domain(const PCIBus *bus);
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 7c40155..728e2d4 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -44,7 +44,7 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
     uint8_t bus_num = addr >> 16;
     uint8_t devfn = addr >> 8;
 
-    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+    return pci_find_device(bus, bus_num, devfn);
 }
 
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
diff --git a/hw/pcie_host.c b/hw/pcie_host.c
index 21069ee..b749865 100644
--- a/hw/pcie_host.c
+++ b/hw/pcie_host.c
@@ -49,8 +49,7 @@ static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
                                                      uint32_t mmcfg_addr)
 {
     return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
-                           PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)),
-                           PCI_FUNC(PCIE_MMCFG_DEVFN(mmcfg_addr)));
+                           PCIE_MMCFG_DEVFN(mmcfg_addr));
 }
 
 static void pcie_mmcfg_data_write(PCIBus *s,
commit 90a20dbb2837f5ff05a9b19659ba1aa218cbd2de
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu Jan 27 15:56:35 2011 +0900

    pci: replace the magic, 256, for the maximum of devfn
    
    Introduce symbol PCI_SLOT_MAX for the # of slots,
    and replace the magic, 256.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.h b/hw/pci.h
index 113e556..7d56337 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -16,6 +16,7 @@
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)         ((devfn) & 0x07)
+#define PCI_SLOT_MAX            32
 #define PCI_FUNC_MAX            8
 
 /* Class, Vendor and Device IDs from Linux's pci_ids.h */
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index e3c93a3..efaefcd 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -22,7 +22,7 @@ struct PCIBus {
     pci_hotplug_fn hotplug;
     DeviceState *hotplug_qdev;
     void *irq_opaque;
-    PCIDevice *devices[256];
+    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
 
commit f64622c401d4975a56b8559e16286231a1d2cfb8
Author: Gleb Natapov <gleb at redhat.com>
Date:   Tue Mar 15 13:56:04 2011 +0200

    report that QEMU process was killed by a signal
    
    Currently when rogue script kills QEMU process (using TERM/INT/HUP
    signal) it looks indistinguishable from system shutdown. Lets report
    that QEMU was killed and leave some clues about the killer identity.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 7971f86..eb49e2f 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -62,9 +62,9 @@ void os_setup_early_signal_handling(void)
     sigaction(SIGPIPE, &act, NULL);
 }
 
-static void termsig_handler(int signal)
+static void termsig_handler(int signal, siginfo_t *info, void *c)
 {
-    qemu_system_shutdown_request();
+    qemu_system_killed(info->si_signo, info->si_pid);
 }
 
 static void sigchld_handler(int signal)
@@ -77,7 +77,8 @@ void os_setup_signal_handling(void)
     struct sigaction act;
 
     memset(&act, 0, sizeof(act));
-    act.sa_handler = termsig_handler;
+    act.sa_sigaction = termsig_handler;
+    act.sa_flags = SA_SIGINFO;
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGHUP,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
diff --git a/sysemu.h b/sysemu.h
index c43c7af..bbbd0fd 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -66,6 +66,8 @@ void qemu_system_vmstop_request(int reason);
 int qemu_shutdown_requested(void);
 int qemu_reset_requested(void);
 int qemu_powerdown_requested(void);
+void qemu_system_killed(int signal, pid_t pid);
+void qemu_kill_report(void);
 extern qemu_irq qemu_system_powerdown;
 void qemu_system_reset(void);
 
diff --git a/vl.c b/vl.c
index c387f2b..192a240 100644
--- a/vl.c
+++ b/vl.c
@@ -1215,7 +1215,8 @@ typedef struct QEMUResetEntry {
 static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
     QTAILQ_HEAD_INITIALIZER(reset_handlers);
 static int reset_requested;
-static int shutdown_requested;
+static int shutdown_requested, shutdown_signal = -1;
+static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
 static int vmstop_requested;
@@ -1227,6 +1228,15 @@ int qemu_shutdown_requested(void)
     return r;
 }
 
+void qemu_kill_report(void)
+{
+    if (shutdown_signal != -1) {
+        fprintf(stderr, "Got signal %d from pid %d\n",
+                         shutdown_signal, shutdown_pid);
+        shutdown_signal = -1;
+    }
+}
+
 int qemu_reset_requested(void)
 {
     int r = reset_requested;
@@ -1300,6 +1310,13 @@ void qemu_system_reset_request(void)
     qemu_notify_event();
 }
 
+void qemu_system_killed(int signal, pid_t pid)
+{
+    shutdown_signal = signal;
+    shutdown_pid = pid;
+    qemu_system_shutdown_request();
+}
+
 void qemu_system_shutdown_request(void)
 {
     shutdown_requested = 1;
@@ -1443,6 +1460,7 @@ static void main_loop(void)
             vm_stop(VMSTOP_DEBUG);
         }
         if (qemu_shutdown_requested()) {
+            qemu_kill_report();
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
             if (no_shutdown) {
                 vm_stop(VMSTOP_SHUTDOWN);
commit bf6b87a883f4067574764acb76024e34abba4aad
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Tue Mar 22 19:11:23 2011 -0400

    rtl8139: add vlan tag insertion
    
    Add support to the emulated hardware to insert vlan tags in packets
    going from the guest to the network.
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Cc: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Cc: Jason Wang <jasowang at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 5b2f489..d545933 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -45,6 +45,7 @@
  *  2010-Feb-04  Frediano Ziglio:   Rewrote timer support using QEMU timer only
  *                                  when strictly needed (required for for
  *                                  Darwin)
+ *  2011-Mar-22  Benjamin Poirier:  Implemented VLAN offloading
  */
 
 /* For crc32 */
@@ -56,6 +57,7 @@
 #include "net.h"
 #include "loader.h"
 #include "sysemu.h"
+#include "iov.h"
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
@@ -1756,22 +1758,52 @@ static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
     return ret;
 }
 
-static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size, int do_interrupt)
+static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
+    int do_interrupt, const uint8_t *dot1q_buf)
 {
+    struct iovec *iov = NULL;
+
     if (!size)
     {
         DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
         return;
     }
 
+    if (dot1q_buf && size >= ETHER_ADDR_LEN * 2) {
+        iov = (struct iovec[3]) {
+            { .iov_base = buf, .iov_len = ETHER_ADDR_LEN * 2 },
+            { .iov_base = (void *) dot1q_buf, .iov_len = VLAN_HLEN },
+            { .iov_base = buf + ETHER_ADDR_LEN * 2,
+                .iov_len = size - ETHER_ADDR_LEN * 2 },
+        };
+    }
+
     if (TxLoopBack == (s->TxConfig & TxLoopBack))
     {
+        size_t buf2_size;
+        uint8_t *buf2;
+
+        if (iov) {
+            buf2_size = iov_size(iov, 3);
+            buf2 = qemu_malloc(buf2_size);
+            iov_to_buf(iov, 3, buf2, 0, buf2_size);
+            buf = buf2;
+        }
+
         DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
         rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt);
+
+        if (iov) {
+            qemu_free(buf2);
+        }
     }
     else
     {
-        qemu_send_packet(&s->nic->nc, buf, size);
+        if (iov) {
+            qemu_sendv_packet(&s->nic->nc, iov, 3);
+        } else {
+            qemu_send_packet(&s->nic->nc, buf, size);
+        }
     }
 }
 
@@ -1805,7 +1837,7 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
     s->TxStatus[descriptor] |= TxHostOwns;
     s->TxStatus[descriptor] |= TxStatOK;
 
-    rtl8139_transfer_frame(s, txbuffer, txsize, 0);
+    rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL);
 
     DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
 
@@ -1932,7 +1964,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
     cpu_physical_memory_read(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
     txdw0 = le32_to_cpu(val);
-    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
     cpu_physical_memory_read(cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
     txdw1 = le32_to_cpu(val);
     cpu_physical_memory_read(cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
@@ -1944,9 +1975,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
            descriptor,
            txdw0, txdw1, txbufLO, txbufHI));
 
-    /* TODO: the following discard cast should clean clang analyzer output */
-    (void)txdw1;
-
 /* w0 ownership flag */
 #define CP_TX_OWN (1<<31)
 /* w0 end of ring flag */
@@ -1970,9 +1998,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 /* w0 bits 0...15 : buffer size */
 #define CP_TX_BUFFER_SIZE (1<<16)
 #define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1)
-/* w1 tag available flag */
-#define CP_RX_TAGC (1<<17)
-/* w1 bits 0...15 : VLAN tag */
+/* w1 add tag flag */
+#define CP_TX_TAGC (1<<17)
+/* w1 bits 0...15 : VLAN tag (big endian) */
 #define CP_TX_VLAN_TAG_MASK ((1<<16) - 1)
 /* w2 low  32bit of Rx buffer ptr */
 /* w3 high 32bit of Rx buffer ptr */
@@ -2072,13 +2100,13 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
     /* update ring data */
     val = cpu_to_le32(txdw0);
     cpu_physical_memory_write(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
-    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
-//    val = cpu_to_le32(txdw1);
-//    cpu_physical_memory_write(cplus_tx_ring_desc+4,  &val, 4);
 
     /* Now decide if descriptor being processed is holding the last segment of packet */
     if (txdw0 & CP_TX_LS)
     {
+        uint8_t dot1q_buffer_space[VLAN_HLEN];
+        uint16_t *dot1q_buffer;
+
         DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
 
         /* can transfer fully assembled packet */
@@ -2087,6 +2115,21 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         int      saved_size    = s->cplus_txbuffer_offset;
         int      saved_buffer_len = s->cplus_txbuffer_len;
 
+        /* create vlan tag */
+        if (txdw1 & CP_TX_TAGC) {
+            /* the vlan tag is in BE byte order in the descriptor
+             * BE + le_to_cpu() + ~swap()~ = cpu */
+            DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with "
+                    "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)));
+
+            dot1q_buffer = (uint16_t *) dot1q_buffer_space;
+            dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
+            /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */
+            dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK);
+        } else {
+            dot1q_buffer = NULL;
+        }
+
         /* reset the card space to protect from recursive call */
         s->cplus_txbuffer = NULL;
         s->cplus_txbuffer_offset = 0;
@@ -2240,7 +2283,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
                         int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
                         DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
-                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
+                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
+                            0, (uint8_t *) dot1q_buffer);
 
                         /* add transferred count to TCP sequence number */
                         p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
@@ -2313,7 +2357,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 
         DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
 
-        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1);
+        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1,
+            (uint8_t *) dot1q_buffer);
 
         /* restore card space if there was no recursion and reset offset */
         if (!s->cplus_txbuffer)
commit 18dabfd1e0fcce17ebf069014eee3aa926707551
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Tue Mar 22 19:11:22 2011 -0400

    rtl8139: add vlan tag extraction
    
    Add support to the emulated hardware to extract vlan tags in packets
    going from the network to the guest.
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Cc: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Cc: Jason Wang <jasowang at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    
    --
    
    AFAIK, extraction is optional to get vlans working. The driver
    requests rx detagging but should not assume that it was done. Under
    Linux, the mac layer will catch the vlan ethertype. I only added this
    part for completeness (to emulate the hardware more truthfully...)
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d843aa0..5b2f489 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -72,6 +72,16 @@
 #define MOD2(input, size) \
     ( ( input ) & ( size - 1 )  )
 
+#define ETHER_ADDR_LEN 6
+#define ETHER_TYPE_LEN 2
+#define ETH_HLEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+#define ETH_P_IP    0x0800      /* Internet Protocol packet */
+#define ETH_P_8021Q 0x8100      /* 802.1Q VLAN Extended Header  */
+#define ETH_MTU     1500
+
+#define VLAN_TCI_LEN 2
+#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN)
+
 #if defined (DEBUG_RTL8139)
 #  define DEBUG_PRINT(x) do { printf x ; } while (0)
 #else
@@ -812,11 +822,13 @@ static int rtl8139_can_receive(VLANClientState *nc)
 static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
 {
     RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    /* size is the length of the buffer passed to the driver */
     int size = size_;
+    const uint8_t *dot1q_buf = NULL;
 
     uint32_t packet_header = 0;
 
-    uint8_t buf1[60];
+    uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];
     static const uint8_t broadcast_macaddr[6] =
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
@@ -928,12 +940,15 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         }
     }
 
-    /* if too small buffer, then expand it */
-    if (size < MIN_BUF_SIZE) {
+    /* if too small buffer, then expand it
+     * Include some tailroom in case a vlan tag is later removed. */
+    if (size < MIN_BUF_SIZE + VLAN_HLEN) {
         memcpy(buf1, buf, size);
-        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
+        memset(buf1 + size, 0, MIN_BUF_SIZE + VLAN_HLEN - size);
         buf = buf1;
-        size = MIN_BUF_SIZE;
+        if (size < MIN_BUF_SIZE) {
+            size = MIN_BUF_SIZE;
+        }
     }
 
     if (rtl8139_cp_receiver_enabled(s))
@@ -996,6 +1011,29 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 
         uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;
 
+        /* write VLAN info to descriptor variables. */
+        if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)
+                &buf[ETHER_ADDR_LEN * 2]) == ETH_P_8021Q) {
+            dot1q_buf = &buf[ETHER_ADDR_LEN * 2];
+            size -= VLAN_HLEN;
+            /* if too small buffer, use the tailroom added duing expansion */
+            if (size < MIN_BUF_SIZE) {
+                size = MIN_BUF_SIZE;
+            }
+
+            rxdw1 &= ~CP_RX_VLAN_TAG_MASK;
+            /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */
+            rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)
+                &dot1q_buf[ETHER_TYPE_LEN]);
+
+            DEBUG_PRINT(("RTL8139: C+ Rx mode : extracted vlan tag with tci: "
+                    "%u\n", be16_to_cpup((uint16_t *)
+                        &dot1q_buf[ETHER_TYPE_LEN])));
+        } else {
+            /* reset VLAN tag flag */
+            rxdw1 &= ~CP_RX_TAVA;
+        }
+
         /* TODO: scatter the packet over available receive ring descriptors space */
 
         if (size+4 > rx_space)
@@ -1017,7 +1055,14 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);
 
         /* receive/copy to target memory */
-        cpu_physical_memory_write( rx_addr, buf, size );
+        if (dot1q_buf) {
+            cpu_physical_memory_write(rx_addr, buf, 2 * ETHER_ADDR_LEN);
+            cpu_physical_memory_write(rx_addr + 2 * ETHER_ADDR_LEN,
+                buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN,
+                size - 2 * ETHER_ADDR_LEN);
+        } else {
+            cpu_physical_memory_write(rx_addr, buf, size);
+        }
 
         if (s->CpCmd & CPlusRxChkSum)
         {
@@ -1025,7 +1070,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         }
 
         /* write checksum */
-        val = cpu_to_le32(crc32(0, buf, size));
+        val = cpu_to_le32(crc32(0, buf, size_));
         cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);
 
 /* first segment of received packet flag */
@@ -1070,9 +1115,6 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK;
         rxdw0 |= (size+4);
 
-        /* reset VLAN tag flag */
-        rxdw1 &= ~CP_RX_TAVA;
-
         /* update ring data */
         val = cpu_to_le32(rxdw0);
         cpu_physical_memory_write(cplus_rx_ring_desc,    (uint8_t *)&val, 4);
@@ -2054,10 +2096,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
         {
             DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n"));
 
-            #define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
-            #define ETH_HLEN    14
-            #define ETH_MTU     1500
-
             /* ip packet header */
             ip_header *ip = NULL;
             int hlen = 0;
commit 2c406b8fc8fc09853e74924d7067712d7a75108f
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Tue Mar 22 19:11:21 2011 -0400

    rtl8139: cleanup FCS calculation
    
    clean out ifdef's around ethernet checksum calculation
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Acked-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Cc: Jason Wang <jasowang at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 0ba51fc..d843aa0 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -47,6 +47,9 @@
  *                                  Darwin)
  */
 
+/* For crc32 */
+#include <zlib.h>
+
 #include "hw.h"
 #include "pci.h"
 #include "qemu-timer.h"
@@ -62,14 +65,6 @@
 /* debug RTL8139 card C+ mode only */
 //#define DEBUG_RTL8139CP 1
 
-/* Calculate CRCs properly on Rx packets */
-#define RTL8139_CALCULATE_RXCRC 1
-
-#if defined(RTL8139_CALCULATE_RXCRC)
-/* For crc32 */
-#include <zlib.h>
-#endif
-
 #define SET_MASKED(input, mask, curr) \
     ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) )
 
@@ -1030,11 +1025,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         }
 
         /* write checksum */
-#if defined (RTL8139_CALCULATE_RXCRC)
         val = cpu_to_le32(crc32(0, buf, size));
-#else
-        val = 0;
-#endif
         cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);
 
 /* first segment of received packet flag */
@@ -1136,12 +1127,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
         rtl8139_write_buffer(s, buf, size);
 
         /* write checksum */
-#if defined (RTL8139_CALCULATE_RXCRC)
         val = cpu_to_le32(crc32(0, buf, size));
-#else
-        val = 0;
-#endif
-
         rtl8139_write_buffer(s, (uint8_t *)&val, 4);
 
         /* correct buffer write pointer */
commit d6e58090fed20e30e6966007bc4df0c04324d9e7
Author: Ulrich Obergfell <uobergfe at redhat.com>
Date:   Fri Mar 25 04:45:54 2011 -0400

    severe memory leak caused by broken palette_destroy() function
    
    The following commit breaks the code of the function palette_destroy().
    
    http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commit;h=e31e3694afef58ba191cbcc6875ec243e5971268
    
    The broken code causes a severe memory leak of 'VncPalette' structures
    because it never frees anything:
    
         70 void palette_destroy(VncPalette *palette)
         71 {
         72     if (palette == NULL) {
         73         qemu_free(palette);
         74     }
         75 }
    
    Version 2 of the patch calls qemu_free() unconditionally.
    
    Signed-off-by: Ulrich Obergfell <uobergfe at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c
index c478060..13ece42 100644
--- a/ui/vnc-palette.c
+++ b/ui/vnc-palette.c
@@ -69,9 +69,7 @@ void palette_init(VncPalette *palette, size_t max, int bpp)
 
 void palette_destroy(VncPalette *palette)
 {
-    if (palette == NULL) {
-        qemu_free(palette);
-    }
+    qemu_free(palette);
 }
 
 int palette_put(VncPalette *palette, uint32_t color)
commit 05175535a3b6c78186ec3538bcd1b01f30ba571e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 23 03:40:57 2011 +0000

    vl.c: Fix compilation failure if CONFIG_SDL isn't defined
    
    Fix a compilation failure if CONFIG_SDL isn't defined (gcc complained
    that the label 'invalid_display' wasn't used).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index dbb927d..c387f2b 100644
--- a/vl.c
+++ b/vl.c
@@ -1575,7 +1575,7 @@ static DisplayType select_display(const char *p)
                 } else if (strstart(opts, "off", &nextopt)) {
                     no_frame = 1;
                 } else {
-                    goto invalid_display;
+                    goto invalid_sdl_args;
                 }
             } else if (strstart(opts, ",alt_grab=", &nextopt)) {
                 opts = nextopt;
@@ -1584,7 +1584,7 @@ static DisplayType select_display(const char *p)
                 } else if (strstart(opts, "off", &nextopt)) {
                     alt_grab = 0;
                 } else {
-                    goto invalid_display;
+                    goto invalid_sdl_args;
                 }
             } else if (strstart(opts, ",ctrl_grab=", &nextopt)) {
                 opts = nextopt;
@@ -1593,7 +1593,7 @@ static DisplayType select_display(const char *p)
                 } else if (strstart(opts, "off", &nextopt)) {
                     ctrl_grab = 0;
                 } else {
-                    goto invalid_display;
+                    goto invalid_sdl_args;
                 }
             } else if (strstart(opts, ",window_close=", &nextopt)) {
                 opts = nextopt;
@@ -1602,10 +1602,12 @@ static DisplayType select_display(const char *p)
                 } else if (strstart(opts, "off", &nextopt)) {
                     no_quit = 1;
                 } else {
-                    goto invalid_display;
+                    goto invalid_sdl_args;
                 }
             } else {
-                goto invalid_display;
+            invalid_sdl_args:
+                fprintf(stderr, "Invalid SDL option string: %s\n", p);
+                exit(1);
             }
             opts = nextopt;
         }
@@ -1642,7 +1644,6 @@ static DisplayType select_display(const char *p)
     } else if (strstart(p, "none", &opts)) {
         display = DT_NONE;
     } else {
-    invalid_display:
         fprintf(stderr, "Unknown display type: %s\n", p);
         exit(1);
     }
commit 56d7a964a5664d3778a0b7a369a5f350d0fe099f
Merge: 24e838b... 2d6c1ef...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 24 08:11:58 2011 -0500

    Merge remote branch 'amit/for-anthony' into staging

commit 24e838b787959eba0bc516d36224df2c6855d02a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Mar 16 15:21:31 2011 +0000

    tcg/arm: Support host code being compiled for Thumb
    
    Although the TCG generated code is always in ARM mode, it is possible
    that the host code was compiled by gcc in Thumb mode (this is often the
    default for Linux distributions targeting ARM v7 only). Handle this
    by using BLX imm when doing a call from ARM into Thumb mode.
    Since BLX imm is not a conditionalisable instruction, we make
    tcg_out_call() no longer take a condition code; we were only ever
    using it with COND_AL anyway.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 918e2f7..fb858d8 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -375,6 +375,12 @@ static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
     tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
 }
 
+static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
+{
+    tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
+                (((offset - 8) >> 2) & 0x00ffffff));
+}
+
 static inline void tcg_out_dat_reg(TCGContext *s,
                 int cond, int opc, int rd, int rn, int rm, int shift)
 {
@@ -840,6 +846,11 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
 {
     int32_t val;
 
+    if (addr & 1) {
+        /* goto to a Thumb destination isn't supported */
+        tcg_abort();
+    }
+
     val = addr - (tcg_target_long) s->code_ptr;
     if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
         tcg_out_b(s, cond, val);
@@ -860,14 +871,22 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
     }
 }
 
-static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
+static inline void tcg_out_call(TCGContext *s, uint32_t addr)
 {
     int32_t val;
 
     val = addr - (tcg_target_long) s->code_ptr;
-    if (val < 0x01fffffd && val > -0x01fffffd)
-        tcg_out_bl(s, cond, val);
-    else {
+    if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
+        if (addr & 1) {
+            /* Use BLX if the target is in Thumb mode */
+            if (!use_armv5_instructions) {
+                tcg_abort();
+            }
+            tcg_out_blx_imm(s, val);
+        } else {
+            tcg_out_bl(s, COND_AL, val);
+        }
+    } else {
 #if 1
         tcg_abort();
 #else
@@ -1063,8 +1082,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
 # endif
-    tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_ld_helpers[s_bits] -
-                    (tcg_target_long) s->code_ptr);
+    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
 
     switch (opc) {
     case 0 | 4:
@@ -1330,8 +1348,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     }
 # endif
 
-    tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits] -
-                    (tcg_target_long) s->code_ptr);
+    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
     if (opc == 3)
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
 
@@ -1443,7 +1460,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_call:
         if (const_args[0])
-            tcg_out_call(s, COND_AL, args[0]);
+            tcg_out_call(s, args[0]);
         else
             tcg_out_callr(s, COND_AL, args[0]);
         break;
commit 4ac8e585c85079f6fd2b2b6da3cb845e3e19459c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 22 07:58:52 2011 -0500

    Revert "x86: Save/restore PAT MSR"
    
    This reverts commit c995b495b9d6e60ab1e390bd398a22425d0b3c8c.
    
    From Jan Kiszka:
    
     Ouch, indeed. Moreover, CPU_SAVE_VERSION was not updated (likely the
     reason for the breakage). Thanks for debugging this!
    
     Anthony (or whoever), please revert this unneeded commit in qemu.git.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/machine.c b/target-i386/machine.c
index 6384f54..d78eceb 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -491,8 +491,6 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(xcr0, CPUState, 12),
         VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
         VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
-
-        VMSTATE_UINT64_V(pat, CPUState, 13),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
commit a0843a68c4e79df801342ec37347dfebc591082e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 22 11:27:33 2011 -0500

    vnc: fix build error from VNC_DIRTY_WORDS
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 2f71769..14f2930 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1659,7 +1659,7 @@ static void framebuffer_update_request(VncState *vs, int incremental,
         for (i = 0; i < h; i++) {
             bitmap_set(vs->dirty[y_position + i], 0, width);
             bitmap_clear(vs->dirty[y_position + i], width,
-                         VNC_DIRTY_WORDS * BITS_PER_LONG - width);
+                         VNC_DIRTY_BITS - width);
         }
     }
 }
commit 6ed391bf90ca8442a6a9c8a29467a8750b1bfb64
Author: Wen Congyang <wency at cn.fujitsu.com>
Date:   Fri Mar 11 17:10:32 2011 +0800

    fix vnc regression
    
    This patch fix the following regression:
    1. we should use bitmap_set() and bitmap_clear() to replace vnc_set_bits().
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 0b5aad2..2f71769 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1645,17 +1645,21 @@ static void framebuffer_update_request(VncState *vs, int incremental,
                                        int x_position, int y_position,
                                        int w, int h)
 {
+    int i;
+    const size_t width = ds_get_width(vs->ds) / 16;
+
     if (y_position > ds_get_height(vs->ds))
         y_position = ds_get_height(vs->ds);
     if (y_position + h >= ds_get_height(vs->ds))
         h = ds_get_height(vs->ds) - y_position;
 
-    int i;
     vs->need_update = 1;
     if (!incremental) {
         vs->force_update = 1;
         for (i = 0; i < h; i++) {
-            bitmap_set(vs->dirty[y_position + i], x_position / 16, w / 16);
+            bitmap_set(vs->dirty[y_position + i], 0, width);
+            bitmap_clear(vs->dirty[y_position + i], width,
+                         VNC_DIRTY_WORDS * BITS_PER_LONG - width);
         }
     }
 }
commit ff73edf514fb5bf18ef4bac0452fff23a5a8b924
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 9 14:31:06 2011 +0100

    qmp-commands.hx: Clean up mess of client_migrate_info
    
    client_migrate_info was put into qmp-commands.hx in the middle of
    migrate_set_speed, between the command and it's description. In
    addition client_migrate_info put the description before the command
    itself, which is the wrong order.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index 1f72a8d..fbd98ee 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -503,79 +503,79 @@ EQMP
     },
 
 SQMP
-client_migrate_info
-------------------
+migrate_set_speed
+-----------------
 
-Set the spice/vnc connection info for the migration target.  The spice/vnc
-server will ask the spice/vnc client to automatically reconnect using the
-new parameters (if specified) once the vm migration finished successfully.
+Set maximum speed for migrations.
 
 Arguments:
 
-- "protocol":     protocol: "spice" or "vnc" (json-string)
-- "hostname":     migration target hostname (json-string)
-- "port":         spice/vnc tcp port for plaintext channels (json-int, optional)
-- "tls-port":     spice tcp port for tls-secured channels (json-int, optional)
-- "cert-subject": server certificate subject (json-string, optional)
+- "value": maximum speed, in bytes per second (json-int)
 
 Example:
 
--> { "execute": "client_migrate_info",
-     "arguments": { "protocol": "spice",
-                    "hostname": "virt42.lab.kraxel.org",
-                    "port": 1234 } }
+-> { "execute": "migrate_set_speed", "arguments": { "value": 1024 } }
 <- { "return": {} }
 
 EQMP
 
     {
-        .name       = "client_migrate_info",
-        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
-        .params     = "protocol hostname port tls-port cert-subject",
-        .help       = "send migration info to spice/vnc client",
+        .name       = "migrate_set_downtime",
+        .args_type  = "value:T",
+        .params     = "value",
+        .help       = "set maximum tolerated downtime (in seconds) for migrations",
         .user_print = monitor_user_noop,
-        .mhandler.cmd_new = client_migrate_info,
+        .mhandler.cmd_new = do_migrate_set_downtime,
     },
 
 SQMP
-migrate_set_speed
------------------
+migrate_set_downtime
+--------------------
 
-Set maximum speed for migrations.
+Set maximum tolerated downtime (in seconds) for migrations.
 
 Arguments:
 
-- "value": maximum speed, in bytes per second (json-int)
+- "value": maximum downtime (json-number)
 
 Example:
 
--> { "execute": "migrate_set_speed", "arguments": { "value": 1024 } }
+-> { "execute": "migrate_set_downtime", "arguments": { "value": 0.1 } }
 <- { "return": {} }
 
 EQMP
 
     {
-        .name       = "migrate_set_downtime",
-        .args_type  = "value:T",
-        .params     = "value",
-        .help       = "set maximum tolerated downtime (in seconds) for migrations",
+        .name       = "client_migrate_info",
+        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+        .params     = "protocol hostname port tls-port cert-subject",
+        .help       = "send migration info to spice/vnc client",
         .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd_new = client_migrate_info,
     },
 
 SQMP
-migrate_set_downtime
---------------------
+client_migrate_info
+------------------
 
-Set maximum tolerated downtime (in seconds) for migrations.
+Set the spice/vnc connection info for the migration target.  The spice/vnc
+server will ask the spice/vnc client to automatically reconnect using the
+new parameters (if specified) once the vm migration finished successfully.
 
 Arguments:
 
-- "value": maximum downtime (json-number)
+- "protocol":     protocol: "spice" or "vnc" (json-string)
+- "hostname":     migration target hostname (json-string)
+- "port":         spice/vnc tcp port for plaintext channels (json-int, optional)
+- "tls-port":     spice tcp port for tls-secured channels (json-int, optional)
+- "cert-subject": server certificate subject (json-string, optional)
 
 Example:
 
--> { "execute": "migrate_set_downtime", "arguments": { "value": 0.1 } }
+-> { "execute": "client_migrate_info",
+     "arguments": { "protocol": "spice",
+                    "hostname": "virt42.lab.kraxel.org",
+                    "port": 1234 } }
 <- { "return": {} }
 
 EQMP
commit 821601ea5b02a68ada479731a4d3d07a9876632a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:36 2011 +0100

    Make VNC support optional
    
    Per default VNC is enabled.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 167ccc2..f8cf199 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -127,19 +127,20 @@ common-obj-y += $(addprefix audio/, $(audio-obj-y))
 ui-obj-y += keymaps.o
 ui-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
 ui-obj-$(CONFIG_CURSES) += curses.o
-ui-obj-y += vnc.o d3des.o
-ui-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
-ui-obj-y += vnc-enc-tight.o vnc-palette.o
-ui-obj-y += vnc-enc-zrle.o
-ui-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
-ui-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
-ui-obj-$(CONFIG_COCOA) += cocoa.o
+vnc-obj-y += vnc.o d3des.o
+vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
+vnc-obj-y += vnc-enc-tight.o vnc-palette.o
+vnc-obj-y += vnc-enc-zrle.o
+vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
+vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
+vnc-obj-$(CONFIG_COCOA) += cocoa.o
 ifdef CONFIG_VNC_THREAD
-ui-obj-y += vnc-jobs-async.o
+vnc-obj-y += vnc-jobs-async.o
 else
-ui-obj-y += vnc-jobs-sync.o
+vnc-obj-y += vnc-jobs-sync.o
 endif
 common-obj-y += $(addprefix ui/, $(ui-obj-y))
+common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
 
 common-obj-y += iov.o acl.o
 common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
diff --git a/configure b/configure
index f594bfe..5a5827f 100755
--- a/configure
+++ b/configure
@@ -117,6 +117,7 @@ kvm=""
 kvm_para=""
 nptl=""
 sdl=""
+vnc="yes"
 sparse="no"
 uuid=""
 vde=""
@@ -539,6 +540,10 @@ for opt do
   ;;
   --enable-sdl) sdl="yes"
   ;;
+  --disable-vnc) vnc="no"
+  ;;
+  --enable-vnc) vnc="yes"
+  ;;
   --fmod-lib=*) fmod_lib="$optarg"
   ;;
   --fmod-inc=*) fmod_inc="$optarg"
@@ -836,6 +841,8 @@ echo "  --disable-strip          disable stripping binaries"
 echo "  --disable-werror         disable compilation abort on warning"
 echo "  --disable-sdl            disable SDL"
 echo "  --enable-sdl             enable SDL"
+echo "  --disable-vnc            disable VNC"
+echo "  --enable-vnc             enable VNC"
 echo "  --enable-cocoa           enable COCOA (Mac OS X only)"
 echo "  --audio-drv-list=LIST    set audio drivers list:"
 echo "                           Available drivers: $audio_possible_drivers"
@@ -1273,7 +1280,7 @@ fi
 
 ##########################################
 # VNC TLS detection
-if test "$vnc_tls" != "no" ; then
+if test "$vnc" = "yes" -a "$vnc_tls" != "no" ; then
   cat > $TMPC <<EOF
 #include <gnutls/gnutls.h>
 int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
@@ -1293,7 +1300,7 @@ fi
 
 ##########################################
 # VNC SASL detection
-if test "$vnc_sasl" != "no" ; then
+if test "$vnc" = "yes" -a "$vnc_sasl" != "no" ; then
   cat > $TMPC <<EOF
 #include <sasl/sasl.h>
 #include <stdio.h>
@@ -1315,7 +1322,7 @@ fi
 
 ##########################################
 # VNC JPEG detection
-if test "$vnc_jpeg" != "no" ; then
+if test "$vnc" = "yes" -a "$vnc_jpeg" != "no" ; then
 cat > $TMPC <<EOF
 #include <stdio.h>
 #include <jpeglib.h>
@@ -1336,7 +1343,7 @@ fi
 
 ##########################################
 # VNC PNG detection
-if test "$vnc_png" != "no" ; then
+if test "$vnc" = "yes" -a "$vnc_png" != "no" ; then
 cat > $TMPC <<EOF
 //#include <stdio.h>
 #include <png.h>
@@ -2495,11 +2502,14 @@ echo "Audio drivers     $audio_drv_list"
 echo "Extra audio cards $audio_card_list"
 echo "Block whitelist   $block_drv_whitelist"
 echo "Mixer emulation   $mixemu"
-echo "VNC TLS support   $vnc_tls"
-echo "VNC SASL support  $vnc_sasl"
-echo "VNC JPEG support  $vnc_jpeg"
-echo "VNC PNG support   $vnc_png"
-echo "VNC thread        $vnc_thread"
+echo "VNC support       $vnc"
+if test "$vnc" = "yes" ; then
+    echo "VNC TLS support   $vnc_tls"
+    echo "VNC SASL support  $vnc_sasl"
+    echo "VNC JPEG support  $vnc_jpeg"
+    echo "VNC PNG support   $vnc_png"
+    echo "VNC thread        $vnc_thread"
+fi
 if test -n "$sparc_cpu"; then
     echo "Target Sparc Arch $sparc_cpu"
 fi
@@ -2649,6 +2659,9 @@ echo "CONFIG_BDRV_WHITELIST=$block_drv_whitelist" >> $config_host_mak
 if test "$mixemu" = "yes" ; then
   echo "CONFIG_MIXEMU=y" >> $config_host_mak
 fi
+if test "$vnc" = "yes" ; then
+  echo "CONFIG_VNC=y" >> $config_host_mak
+fi
 if test "$vnc_tls" = "yes" ; then
   echo "CONFIG_VNC_TLS=y" >> $config_host_mak
   echo "VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_host_mak
@@ -2657,15 +2670,15 @@ if test "$vnc_sasl" = "yes" ; then
   echo "CONFIG_VNC_SASL=y" >> $config_host_mak
   echo "VNC_SASL_CFLAGS=$vnc_sasl_cflags" >> $config_host_mak
 fi
-if test "$vnc_jpeg" != "no" ; then
+if test "$vnc_jpeg" = "yes" ; then
   echo "CONFIG_VNC_JPEG=y" >> $config_host_mak
   echo "VNC_JPEG_CFLAGS=$vnc_jpeg_cflags" >> $config_host_mak
 fi
-if test "$vnc_png" != "no" ; then
+if test "$vnc_png" = "yes" ; then
   echo "CONFIG_VNC_PNG=y" >> $config_host_mak
   echo "VNC_PNG_CFLAGS=$vnc_png_cflags" >> $config_host_mak
 fi
-if test "$vnc_thread" != "no" ; then
+if test "$vnc_thread" = "yes" ; then
   echo "CONFIG_VNC_THREAD=y" >> $config_host_mak
 fi
 if test "$fnmatch" = "yes" ; then
diff --git a/console.h b/console.h
index 711895e..64d1f09 100644
--- a/console.h
+++ b/console.h
@@ -4,6 +4,8 @@
 #include "qemu-char.h"
 #include "qdict.h"
 #include "notify.h"
+#include "qerror.h"
+#include "monitor.h"
 
 /* keyboard/mouse support */
 
@@ -370,12 +372,32 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
 void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
 int vnc_display_open(DisplayState *ds, const char *display);
-int vnc_display_password(DisplayState *ds, const char *password);
 int vnc_display_disable_login(DisplayState *ds);
+char *vnc_display_local_addr(DisplayState *ds);
+#ifdef CONFIG_VNC
+int vnc_display_password(DisplayState *ds, const char *password);
 int vnc_display_pw_expire(DisplayState *ds, time_t expires);
 void do_info_vnc_print(Monitor *mon, const QObject *data);
 void do_info_vnc(Monitor *mon, QObject **ret_data);
-char *vnc_display_local_addr(DisplayState *ds);
+#else
+static inline int vnc_display_password(DisplayState *ds, const char *password)
+{
+    qerror_report(QERR_FEATURE_DISABLED, "vnc");
+    return -ENODEV;
+}
+static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
+{
+    qerror_report(QERR_FEATURE_DISABLED, "vnc");
+    return -ENODEV;
+};
+static inline void do_info_vnc(Monitor *mon, QObject **ret_data)
+{
+};
+static inline void do_info_vnc_print(Monitor *mon, const QObject *data)
+{
+    monitor_printf(mon, "VNC support disabled\n");
+};
+#endif
 
 /* curses.c */
 void curses_display_init(DisplayState *ds, int full_screen);
diff --git a/monitor.c b/monitor.c
index 552e951..76a8207 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1020,6 +1020,7 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
+#ifdef CONFIG_VNC
 static int change_vnc_password(const char *password)
 {
     if (!password || !password[0]) {
@@ -1066,6 +1067,13 @@ static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
 
     return 0;
 }
+#else
+static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
+{
+    qerror_report(QERR_FEATURE_DISABLED, "vnc");
+    return -ENODEV;
+}
+#endif
 
 /**
  * do_change(): Change a removable medium, or VNC configuration
@@ -1131,12 +1139,7 @@ static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
         }
         /* Note that setting an empty password will not disable login through
          * this interface. */
-        rc = vnc_display_password(NULL, password);
-        if (rc != 0) {
-            qerror_report(QERR_SET_PASSWD_FAILED);
-            return -1;
-        }
-        return 0;
+        return vnc_display_password(NULL, password);
     }
 
     qerror_report(QERR_INVALID_PARAMETER, "protocol");
@@ -1175,12 +1178,7 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     if (strcmp(protocol, "vnc") == 0) {
-        rc = vnc_display_pw_expire(NULL, when);
-        if (rc != 0) {
-            qerror_report(QERR_SET_PASSWD_FAILED);
-            return -1;
-        }
-        return 0;
+        return vnc_display_pw_expire(NULL, when);
     }
 
     qerror_report(QERR_INVALID_PARAMETER, "protocol");
diff --git a/qerror.h b/qerror.h
index f732d45..df61d2c 100644
--- a/qerror.h
+++ b/qerror.h
@@ -171,4 +171,7 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_VNC_SERVER_FAILED \
     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
 
+#define QERR_FEATURE_DISABLED \
+    "{ 'class': 'FeatureDisabled', 'data': { 'name': %s } }"
+
 #endif /* QERROR_H */
diff --git a/ui/vnc.c b/ui/vnc.c
index fdc4a70..0b5aad2 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2638,16 +2638,19 @@ int vnc_display_disable_login(DisplayState *ds)
 
 int vnc_display_password(DisplayState *ds, const char *password)
 {
+    int ret = 0;
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
 
     if (!vs) {
-        return -1;
+        ret = -EINVAL;
+        goto out;
     }
 
     if (!password) {
         /* This is not the intention of this interface but err on the side
            of being safe */
-        return vnc_display_disable_login(ds);
+        ret = vnc_display_disable_login(ds);
+        goto out;
     }
 
     if (vs->password) {
@@ -2656,8 +2659,11 @@ int vnc_display_password(DisplayState *ds, const char *password)
     }
     vs->password = qemu_strdup(password);
     vs->auth = VNC_AUTH_VNC;
-
-    return 0;
+out:
+    if (ret != 0) {
+        qerror_report(QERR_SET_PASSWD_FAILED);
+    }
+    return ret;
 }
 
 int vnc_display_pw_expire(DisplayState *ds, time_t expires)
diff --git a/vl.c b/vl.c
index 11ad8fb..dbb927d 100644
--- a/vl.c
+++ b/vl.c
@@ -206,7 +206,9 @@ int smp_cpus = 1;
 int max_cpus = 0;
 int smp_cores = 1;
 int smp_threads = 1;
+#ifdef CONFIG_VNC
 const char *vnc_display;
+#endif
 int acpi_enabled = 1;
 int no_hpet = 0;
 int fd_bootchk = 1;
@@ -1612,6 +1614,7 @@ static DisplayType select_display(const char *p)
         exit(1);
 #endif
     } else if (strstart(p, "vnc", &opts)) {
+#ifdef CONFIG_VNC
         display_remote++;
 
         if (*opts) {
@@ -1625,6 +1628,10 @@ static DisplayType select_display(const char *p)
             fprintf(stderr, "VNC requires a display argument vnc=<display>\n");
             exit(1);
         }
+#else
+        fprintf(stderr, "VNC support is disabled\n");
+        exit(1);
+#endif
     } else if (strstart(p, "curses", &opts)) {
 #ifdef CONFIG_CURSES
         display = DT_CURSES;
@@ -2026,7 +2033,9 @@ int main(int argc, char **argv, char **envp)
     int tb_size;
     const char *pid_file = NULL;
     const char *incoming = NULL;
+#ifdef CONFIG_VNC
     int show_vnc_port = 0;
+#endif
     int defconfig = 1;
     const char *trace_file = NULL;
 
@@ -2684,9 +2693,14 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
 	    case QEMU_OPTION_vnc:
+#ifdef CONFIG_VNC
                 display_remote++;
-		vnc_display = optarg;
-		break;
+                vnc_display = optarg;
+#else
+                fprintf(stderr, "VNC support is disabled\n");
+                exit(1);
+#endif
+                break;
             case QEMU_OPTION_no_acpi:
                 acpi_enabled = 0;
                 break;
@@ -3142,12 +3156,14 @@ int main(int argc, char **argv, char **envp)
     if (display_type == DT_DEFAULT && !display_remote) {
 #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
         display_type = DT_SDL;
-#else
+#elif defined(CONFIG_VNC)
         vnc_display = "localhost:0,to=99";
         show_vnc_port = 1;
+#else
+        display_type = DT_NONE;
 #endif
     }
-        
+
 
     /* init local displays */
     switch (display_type) {
@@ -3171,6 +3187,7 @@ int main(int argc, char **argv, char **envp)
         break;
     }
 
+#ifdef CONFIG_VNC
     /* init remote displays */
     if (vnc_display) {
         vnc_display_init(ds);
@@ -3181,6 +3198,7 @@ int main(int argc, char **argv, char **envp)
             printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
         }
     }
+#endif
 #ifdef CONFIG_SPICE
     if (using_spice && !qxl_enabled) {
         qemu_spice_display_init(ds);
commit 47b053690e8582ab52e09181c2c3f19a2ade134f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:35 2011 +0100

    error message if user specifies curses on cmd line when curses is disabled
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 1193d94..ef60730 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -634,11 +634,9 @@ the console. Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 ETEXI
 
-#ifdef CONFIG_CURSES
 DEF("curses", 0, QEMU_OPTION_curses,
     "-curses         use a curses/ncurses interface instead of SDL\n",
     QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -curses
 @findex curses
diff --git a/vl.c b/vl.c
index 4ca4192..11ad8fb 100644
--- a/vl.c
+++ b/vl.c
@@ -2247,11 +2247,14 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_nographic:
                 display_type = DT_NOGRAPHIC;
                 break;
-#ifdef CONFIG_CURSES
             case QEMU_OPTION_curses:
+#ifdef CONFIG_CURSES
                 display_type = DT_CURSES;
-                break;
+#else
+                fprintf(stderr, "Curses support is disabled\n");
+                exit(1);
 #endif
+                break;
             case QEMU_OPTION_portrait:
                 graphic_rotate = 1;
                 break;
commit 58fc096c76e4093d652d75c01112300a2d5f609e
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:34 2011 +0100

    error message if user specifies SDL cmd line option when SDL is disabled
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 5f8dc04..1193d94 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -647,11 +647,9 @@ QEMU can display the VGA output when in text mode using a
 curses/ncurses interface.  Nothing is displayed in graphical mode.
 ETEXI
 
-#ifdef CONFIG_SDL
 DEF("no-frame", 0, QEMU_OPTION_no_frame,
     "-no-frame       open SDL window without a frame and window decorations\n",
     QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -no-frame
 @findex -no-frame
@@ -660,42 +658,34 @@ available screen space. This makes the using QEMU in a dedicated desktop
 workspace more convenient.
 ETEXI
 
-#ifdef CONFIG_SDL
 DEF("alt-grab", 0, QEMU_OPTION_alt_grab,
     "-alt-grab       use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n",
     QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -alt-grab
 @findex -alt-grab
 Use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt).
 ETEXI
 
-#ifdef CONFIG_SDL
 DEF("ctrl-grab", 0, QEMU_OPTION_ctrl_grab,
     "-ctrl-grab      use Right-Ctrl to grab mouse (instead of Ctrl-Alt)\n",
     QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -ctrl-grab
 @findex -ctrl-grab
 Use Right-Ctrl to grab mouse (instead of Ctrl-Alt).
 ETEXI
 
-#ifdef CONFIG_SDL
 DEF("no-quit", 0, QEMU_OPTION_no_quit,
     "-no-quit        disable SDL window close capability\n", QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -no-quit
 @findex -no-quit
 Disable SDL window close capability.
 ETEXI
 
-#ifdef CONFIG_SDL
 DEF("sdl", 0, QEMU_OPTION_sdl,
     "-sdl            enable SDL\n", QEMU_ARCH_ALL)
-#endif
 STEXI
 @item -sdl
 @findex -sdl
diff --git a/vl.c b/vl.c
index 1cb7ce2..4ca4192 100644
--- a/vl.c
+++ b/vl.c
@@ -2625,6 +2625,14 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_sdl:
                 display_type = DT_SDL;
                 break;
+#else
+            case QEMU_OPTION_no_frame:
+            case QEMU_OPTION_alt_grab:
+            case QEMU_OPTION_ctrl_grab:
+            case QEMU_OPTION_no_quit:
+            case QEMU_OPTION_sdl:
+                fprintf(stderr, "SDL support is disabled\n");
+                exit(1);
 #endif
             case QEMU_OPTION_pidfile:
                 pid_file = optarg;
commit 3264ff120c032df83ae3f6aa84fbe90ff55a3a13
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:33 2011 +0100

    Add support for -display vnc
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 08a99b5..5f8dc04 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -592,7 +592,8 @@ ETEXI
 
 DEF("display", HAS_ARG, QEMU_OPTION_display,
     "-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
-    "            [,window_close=on|off]|curses|none\n"
+    "            [,window_close=on|off]|curses|none|\n"
+    "            vnc=<display>[,<optargs>]\n"
     "                select display type\n", QEMU_ARCH_ALL)
 STEXI
 @item -display @var{type}
@@ -615,6 +616,8 @@ graphics card, but its output will not be displayed to the QEMU
 user. This option differs from the -nographic option in that it
 only affects what is done with video output; -nographic also changes
 the destination of the serial and parallel port data.
+ at item vnc
+Start a VNC server on display <arg>
 @end table
 ETEXI
 
diff --git a/vl.c b/vl.c
index 2da2136..1cb7ce2 100644
--- a/vl.c
+++ b/vl.c
@@ -1611,6 +1611,20 @@ static DisplayType select_display(const char *p)
         fprintf(stderr, "SDL support is disabled\n");
         exit(1);
 #endif
+    } else if (strstart(p, "vnc", &opts)) {
+        display_remote++;
+
+        if (*opts) {
+            const char *nextopt;
+
+            if (strstart(opts, "=", &nextopt)) {
+                vnc_display = nextopt;
+            }
+        }
+        if (!vnc_display) {
+            fprintf(stderr, "VNC requires a display argument vnc=<display>\n");
+            exit(1);
+        }
     } else if (strstart(p, "curses", &opts)) {
 #ifdef CONFIG_CURSES
         display = DT_CURSES;
commit 4171d32e6eea47bf2cd160ace0ec3639e10b3aa9
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:32 2011 +0100

    Introduce -display none
    
    New option -display none. This option differs from -nographic by not
    trying to take control of stdio etc. but instead behaves as if a
    graphics display is enabled, except that it doesn't show one.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index a3191e6..08a99b5 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -592,7 +592,7 @@ ETEXI
 
 DEF("display", HAS_ARG, QEMU_OPTION_display,
     "-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
-    "            [,window_close=on|off]|curses\n"
+    "            [,window_close=on|off]|curses|none\n"
     "                select display type\n", QEMU_ARCH_ALL)
 STEXI
 @item -display @var{type}
@@ -609,6 +609,12 @@ support a text mode, QEMU can display this output using a
 curses/ncurses interface. Nothing is displayed when the graphics
 device is in graphical mode or if the graphics device does not support
 a text mode. Generally only the VGA device models support text mode.
+ at item none
+Do not display video output. The guest will still see an emulated
+graphics card, but its output will not be displayed to the QEMU
+user. This option differs from the -nographic option in that it
+only affects what is done with video output; -nographic also changes
+the destination of the serial and parallel port data.
 @end table
 ETEXI
 
diff --git a/sysemu.h b/sysemu.h
index 0a83ab9..c43c7af 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -110,6 +110,7 @@ typedef enum DisplayType
     DT_CURSES,
     DT_SDL,
     DT_NOGRAPHIC,
+    DT_NONE,
 } DisplayType;
 
 extern int autostart;
diff --git a/vl.c b/vl.c
index dd026aa..2da2136 100644
--- a/vl.c
+++ b/vl.c
@@ -1618,6 +1618,8 @@ static DisplayType select_display(const char *p)
         fprintf(stderr, "Curses support is disabled\n");
         exit(1);
 #endif
+    } else if (strstart(p, "none", &opts)) {
+        display = DT_NONE;
     } else {
     invalid_display:
         fprintf(stderr, "Unknown display type: %s\n", p);
commit 1472a95bab1e7dc4d6cab83dc3853574cb829211
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:31 2011 +0100

    Introduce -display argument
    
    This patch introduces a -display argument which consolidates the
    setting of the display mode. Valid options are:
    sdl/curses/default
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index badb730..a3191e6 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -590,6 +590,28 @@ STEXI
 @table @option
 ETEXI
 
+DEF("display", HAS_ARG, QEMU_OPTION_display,
+    "-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
+    "            [,window_close=on|off]|curses\n"
+    "                select display type\n", QEMU_ARCH_ALL)
+STEXI
+ at item -display @var{type}
+ at findex -display
+Select type of display to use. This option is a replacement for the
+old style -sdl/-curses/... options. Valid values for @var{type} are
+ at table @option
+ at item sdl
+Display video output via SDL (usually in a separate graphics
+window; see the SDL documentation for other possibilities).
+ at item curses
+Display video output via curses. For graphics device models which
+support a text mode, QEMU can display this output using a
+curses/ncurses interface. Nothing is displayed when the graphics
+device is in graphical mode or if the graphics device does not support
+a text mode. Generally only the VGA device models support text mode.
+ at end table
+ETEXI
+
 DEF("nographic", 0, QEMU_OPTION_nographic,
     "-nographic      disable graphical output and redirect serial I/Os to console\n",
     QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index ac47211..dd026aa 100644
--- a/vl.c
+++ b/vl.c
@@ -1555,6 +1555,78 @@ static void select_vgahw (const char *p)
     }
 }
 
+static DisplayType select_display(const char *p)
+{
+    const char *opts;
+    DisplayType display = DT_DEFAULT;
+
+    if (strstart(p, "sdl", &opts)) {
+#ifdef CONFIG_SDL
+        display = DT_SDL;
+        while (*opts) {
+            const char *nextopt;
+
+            if (strstart(opts, ",frame=", &nextopt)) {
+                opts = nextopt;
+                if (strstart(opts, "on", &nextopt)) {
+                    no_frame = 0;
+                } else if (strstart(opts, "off", &nextopt)) {
+                    no_frame = 1;
+                } else {
+                    goto invalid_display;
+                }
+            } else if (strstart(opts, ",alt_grab=", &nextopt)) {
+                opts = nextopt;
+                if (strstart(opts, "on", &nextopt)) {
+                    alt_grab = 1;
+                } else if (strstart(opts, "off", &nextopt)) {
+                    alt_grab = 0;
+                } else {
+                    goto invalid_display;
+                }
+            } else if (strstart(opts, ",ctrl_grab=", &nextopt)) {
+                opts = nextopt;
+                if (strstart(opts, "on", &nextopt)) {
+                    ctrl_grab = 1;
+                } else if (strstart(opts, "off", &nextopt)) {
+                    ctrl_grab = 0;
+                } else {
+                    goto invalid_display;
+                }
+            } else if (strstart(opts, ",window_close=", &nextopt)) {
+                opts = nextopt;
+                if (strstart(opts, "on", &nextopt)) {
+                    no_quit = 0;
+                } else if (strstart(opts, "off", &nextopt)) {
+                    no_quit = 1;
+                } else {
+                    goto invalid_display;
+                }
+            } else {
+                goto invalid_display;
+            }
+            opts = nextopt;
+        }
+#else
+        fprintf(stderr, "SDL support is disabled\n");
+        exit(1);
+#endif
+    } else if (strstart(p, "curses", &opts)) {
+#ifdef CONFIG_CURSES
+        display = DT_CURSES;
+#else
+        fprintf(stderr, "Curses support is disabled\n");
+        exit(1);
+#endif
+    } else {
+    invalid_display:
+        fprintf(stderr, "Unknown display type: %s\n", p);
+        exit(1);
+    }
+
+    return display;
+}
+
 static int balloon_parse(const char *arg)
 {
     QemuOpts *opts;
@@ -2153,6 +2225,9 @@ int main(int argc, char **argv, char **envp)
                 }
                 numa_add(optarg);
                 break;
+            case QEMU_OPTION_display:
+                display_type = select_display(optarg);
+                break;
             case QEMU_OPTION_nographic:
                 display_type = DT_NOGRAPHIC;
                 break;
commit ffe8b821a1ac7d3318b00004e37f13615ff60a9f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 16 13:33:30 2011 +0100

    Consolidate DisplaySurface allocation in qemu_alloc_display()
    
    This removes various code duplication from console.e and sdl.c
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index 12407b3..871c1d4 100644
--- a/console.c
+++ b/console.c
@@ -1278,38 +1278,40 @@ static DisplaySurface* defaultallocator_create_displaysurface(int width, int hei
 {
     DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
 
-    surface->width = width;
-    surface->height = height;
-    surface->linesize = width * 4;
-    surface->pf = qemu_default_pixelformat(32);
-#ifdef HOST_WORDS_BIGENDIAN
-    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
-    surface->flags = QEMU_ALLOCATED_FLAG;
-#endif
-    surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
-
+    int linesize = width * 4;
+    qemu_alloc_display(surface, width, height, linesize,
+                       qemu_default_pixelformat(32), 0);
     return surface;
 }
 
 static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
                                           int width, int height)
 {
+    int linesize = width * 4;
+    qemu_alloc_display(surface, width, height, linesize,
+                       qemu_default_pixelformat(32), 0);
+    return surface;
+}
+
+void qemu_alloc_display(DisplaySurface *surface, int width, int height,
+                        int linesize, PixelFormat pf, int newflags)
+{
+    void *data;
     surface->width = width;
     surface->height = height;
-    surface->linesize = width * 4;
-    surface->pf = qemu_default_pixelformat(32);
-    if (surface->flags & QEMU_ALLOCATED_FLAG)
-        surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
-    else
-        surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
+    surface->linesize = linesize;
+    surface->pf = pf;
+    if (surface->flags & QEMU_ALLOCATED_FLAG) {
+        data = qemu_realloc(surface->data,
+                            surface->linesize * surface->height);
+    } else {
+        data = qemu_malloc(surface->linesize * surface->height);
+    }
+    surface->data = (uint8_t *)data;
+    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
 #ifdef HOST_WORDS_BIGENDIAN
-    surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
-    surface->flags = QEMU_ALLOCATED_FLAG;
+    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
 #endif
-
-    return surface;
 }
 
 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
diff --git a/console.h b/console.h
index f4e4741..711895e 100644
--- a/console.h
+++ b/console.h
@@ -189,6 +189,8 @@ void register_displaystate(DisplayState *ds);
 DisplayState *get_displaystate(void);
 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
                                                 int linesize, uint8_t *data);
+void qemu_alloc_display(DisplaySurface *surface, int width, int height,
+                        int linesize, PixelFormat pf, int newflags);
 PixelFormat qemu_different_endianness_pixelformat(int bpp);
 PixelFormat qemu_default_pixelformat(int bpp);
 
diff --git a/ui/sdl.c b/ui/sdl.c
index 47ac49c..c5bb0a3 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -176,22 +176,18 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
 
     surface->width = width;
     surface->height = height;
-    
+
     if (scaling_active) {
+        int linesize;
+        PixelFormat pf;
         if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
-            surface->linesize = width * 4;
-            surface->pf = qemu_default_pixelformat(32);
+            linesize = width * 4;
+            pf = qemu_default_pixelformat(32);
         } else {
-            surface->linesize = width * host_format.BytesPerPixel;
-            surface->pf = sdl_to_qemu_pixelformat(&host_format);
+            linesize = width * host_format.BytesPerPixel;
+            pf = sdl_to_qemu_pixelformat(&host_format);
         }
-#ifdef HOST_WORDS_BIGENDIAN
-        surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
-        surface->flags = QEMU_ALLOCATED_FLAG;
-#endif
-        surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
-
+        qemu_alloc_display(surface, width, height, linesize, pf, 0);
         return surface;
     }
 
commit 6aae3df15dc31f3635efe6e4d4605a6f16888a1b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 14 15:37:13 2011 +0000

    target-arm: use make_float32() to make constant floats for VRSQRTS
    
    The preferred way to create a constant floating point value is to use
    make_float32() rather than doing a runtime int32_to_float32().
    Convert the code in the VRSQRTS helper to work this way.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6c0e59f..78f3d39 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2708,6 +2708,8 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
 }
 
 #define float32_two make_float32(0x40000000)
+#define float32_three make_float32(0x40400000)
+#define float32_one_point_five make_float32(0x3fc00000)
 
 float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
 {
@@ -2722,16 +2724,13 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
 float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
 {
     float_status *s = &env->vfp.standard_fp_status;
-    float32 two = int32_to_float32(2, s);
-    float32 three = int32_to_float32(3, s);
     float32 product;
     if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
         (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
-        product = float32_zero;
-    } else {
-        product = float32_mul(a, b, s);
+        return float32_one_point_five;
     }
-    return float32_div(float32_sub(three, product, s), two, s);
+    product = float32_mul(a, b, s);
+    return float32_div(float32_sub(float32_three, product, s), float32_two, s);
 }
 
 /* NEON helpers.  */
commit dda3ec490cf6a5927a9c6829654481101bfeda61
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 14 15:37:12 2011 +0000

    target-arm: Fix VRECPS edge cases handling
    
    Correct the handling of edge cases for the VRECPS instruction:
     * this is a Neon instruction so uses the "standard FPSCR value"
     * (zero, inf) is a special case which returns 2.0
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4f2b440..6c0e59f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2707,11 +2707,16 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
     return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
 }
 
+#define float32_two make_float32(0x40000000)
+
 float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
 {
-    float_status *s = &env->vfp.fp_status;
-    float32 two = int32_to_float32(2, s);
-    return float32_sub(two, float32_mul(a, b, s), s);
+    float_status *s = &env->vfp.standard_fp_status;
+    if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
+        (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
+        return float32_two;
+    }
+    return float32_sub(float32_two, float32_mul(a, b, s), s);
 }
 
 float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
commit 7d2aabe262846ddeda1785d42ff4d7964e8ac1c8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 13:32:34 2011 +0000

    target-arm: Fix TCG temporary leaks for scalar VMULL
    
    Fix a TCG temporary leak when translating 32-bit scalar VMULL.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2351c31..f69912f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4157,10 +4157,12 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
     case 4:
         tmp = gen_muls_i64_i32(a, b);
         tcg_gen_mov_i64(dest, tmp);
+        tcg_temp_free_i64(tmp);
         break;
     case 5:
         tmp = gen_mulu_i64_i32(a, b);
         tcg_gen_mov_i64(dest, tmp);
+        tcg_temp_free_i64(tmp);
         break;
     default: abort();
     }
commit e1d177b922f52569e900e96d611caa09655bdec9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 11 10:09:58 2011 +0000

    target-arm: Set Q bit for overflow in SMUAD and SMLAD
    
    SMUAD and SMLAD are supposed to set the Q bit if the addition of
    the two 16x16 multiply products and optional accumulator overflows
    considered as a signed value. However we were only doing this check
    for the addition of the accumulator, not when adding the products,
    with the effect that we were mishandling the edge case where
    both inputs are 0x80008000.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0afdbfb..2351c31 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7038,11 +7038,15 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         if (insn & (1 << 5))
                             gen_swap_half(tmp2);
                         gen_smul_dual(tmp, tmp2);
-                        /* This addition cannot overflow.  */
                         if (insn & (1 << 6)) {
+                            /* This subtraction cannot overflow. */
                             tcg_gen_sub_i32(tmp, tmp, tmp2);
                         } else {
-                            tcg_gen_add_i32(tmp, tmp, tmp2);
+                            /* This addition cannot overflow 32 bits;
+                             * however it may overflow considered as a signed
+                             * operation, in which case we must set the Q flag.
+                             */
+                            gen_helper_add_setq(tmp, tmp, tmp2);
                         }
                         tcg_temp_free_i32(tmp2);
                         if (insn & (1 << 22)) {
@@ -7860,11 +7864,15 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 if (op)
                     gen_swap_half(tmp2);
                 gen_smul_dual(tmp, tmp2);
-                /* This addition cannot overflow.  */
                 if (insn & (1 << 22)) {
+                    /* This subtraction cannot overflow. */
                     tcg_gen_sub_i32(tmp, tmp, tmp2);
                 } else {
-                    tcg_gen_add_i32(tmp, tmp, tmp2);
+                    /* This addition cannot overflow 32 bits;
+                     * however it may overflow considered as a signed
+                     * operation, in which case we must set the Q flag.
+                     */
+                    gen_helper_add_setq(tmp, tmp, tmp2);
                 }
                 tcg_temp_free_i32(tmp2);
                 if (rs != 15)
commit db6e2e65adddfcdc3f81026df7fd490e13813e8a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 10 18:51:49 2011 +0000

    target-arm: Fix GE bits for v6media signed modulo arithmetic
    
    Fix the signed modulo arithmetic helpers for the v6media
    instructions (SADD8, SSUB8, SADD16, SSUB16, SASX, SSAX) to set
    the GE bits correctly (based on the result of the add or subtract
    before it is truncated to 16 bits, not after).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index d360121..4f2b440 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2171,7 +2171,7 @@ static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
 /* Signed modulo arithmetic.  */
 #define SARITH16(a, b, n, op) do { \
     int32_t sum; \
-    sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \
+    sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
     RESULT(sum, n, 16); \
     if (sum >= 0) \
         ge |= 3 << (n * 2); \
@@ -2179,7 +2179,7 @@ static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
 
 #define SARITH8(a, b, n, op) do { \
     int32_t sum; \
-    sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \
+    sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
     RESULT(sum, n, 8); \
     if (sum >= 0) \
         ge |= 1 << n; \
commit 2a0308c54f8afb606d4185d59d502823be3c307b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 10 16:48:49 2011 +0000

    target-arm: Fix UNDEF cases in Thumb load/store
    
    Decode of Thumb load/store was merging together the cases of 'bit 11==0'
    (reg+reg LSL imm) and 'bit 11==1' (reg+imm). This happens to work for
    valid instruction patterns but meant that we would not UNDEF for the
    cases the architecture mandates that we must. Make the decode actually
    look at bit 11 as well as [10..8] so that we UNDEF in the right places.
    
    This change also removes what was a spurious unreachable 'case 8',
    and correctly frees TCG temporaries on the illegal-insn codepaths.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 062de5e..0afdbfb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8378,39 +8378,42 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 tcg_gen_addi_i32(addr, addr, imm);
             } else {
                 imm = insn & 0xff;
-                switch ((insn >> 8) & 7) {
-                case 0: case 8: /* Shifted Register.  */
+                switch ((insn >> 8) & 0xf) {
+                case 0x0: /* Shifted Register.  */
                     shift = (insn >> 4) & 0xf;
-                    if (shift > 3)
+                    if (shift > 3) {
+                        tcg_temp_free_i32(addr);
                         goto illegal_op;
+                    }
                     tmp = load_reg(s, rm);
                     if (shift)
                         tcg_gen_shli_i32(tmp, tmp, shift);
                     tcg_gen_add_i32(addr, addr, tmp);
                     tcg_temp_free_i32(tmp);
                     break;
-                case 4: /* Negative offset.  */
+                case 0xc: /* Negative offset.  */
                     tcg_gen_addi_i32(addr, addr, -imm);
                     break;
-                case 6: /* User privilege.  */
+                case 0xe: /* User privilege.  */
                     tcg_gen_addi_i32(addr, addr, imm);
                     user = 1;
                     break;
-                case 1: /* Post-decrement.  */
+                case 0x9: /* Post-decrement.  */
                     imm = -imm;
                     /* Fall through.  */
-                case 3: /* Post-increment.  */
+                case 0xb: /* Post-increment.  */
                     postinc = 1;
                     writeback = 1;
                     break;
-                case 5: /* Pre-decrement.  */
+                case 0xd: /* Pre-decrement.  */
                     imm = -imm;
                     /* Fall through.  */
-                case 7: /* Pre-increment.  */
+                case 0xf: /* Pre-increment.  */
                     tcg_gen_addi_i32(addr, addr, imm);
                     writeback = 1;
                     break;
                 default:
+                    tcg_temp_free_i32(addr);
                     goto illegal_op;
                 }
             }
@@ -8423,7 +8426,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             case 1: tmp = gen_ld16u(addr, user); break;
             case 5: tmp = gen_ld16s(addr, user); break;
             case 2: tmp = gen_ld32(addr, user); break;
-            default: goto illegal_op;
+            default:
+                tcg_temp_free_i32(addr);
+                goto illegal_op;
             }
             if (rs == 15) {
                 gen_bx(s, tmp);
@@ -8437,7 +8442,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             case 0: gen_st8(tmp, addr, user); break;
             case 1: gen_st16(tmp, addr, user); break;
             case 2: gen_st32(tmp, addr, user); break;
-            default: goto illegal_op;
+            default:
+                tcg_temp_free_i32(addr);
+                goto illegal_op;
             }
         }
         if (postinc)
commit 30cb4cdec79dc2727f562edee36a4f3df4dfc23f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 25 10:27:40 2011 +0000

    linux-user: Fix unlock_user() call in return from poll()
    
    Correct the broken attempt to calculate the third argument
    to unlock_user() in the code path which unlocked the pollfd
    array on return from poll() and ppoll() emulation. (This
    only caused a problem if unlock_user() wasn't a no-op, eg
    if DEBUG_REMAP is defined.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 23d7a63..bb0999d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6318,10 +6318,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 for(i = 0; i < nfds; i++) {
                     target_pfd[i].revents = tswap16(pfd[i].revents);
                 }
-                ret += nfds * (sizeof(struct target_pollfd)
-                               - sizeof(struct pollfd));
             }
-            unlock_user(target_pfd, arg1, ret);
+            unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
         }
         break;
 #endif
commit ff90d50393e4485e336ec57e157eee0f5d116d91
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Mar 21 10:53:00 2011 +0100

    vmmouse: Register vmstate via qdev
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index ab8dbd6..1113f33 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -265,7 +265,6 @@ static int vmmouse_initfn(ISADevice *dev)
     vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
     vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
-    vmstate_register(NULL, 0, &vmstate_vmmouse, s);
 
     return 0;
 }
@@ -274,6 +273,7 @@ static ISADeviceInfo vmmouse_info = {
     .init          = vmmouse_initfn,
     .qdev.name     = "vmmouse",
     .qdev.size     = sizeof(VMMouseState),
+    .qdev.vmsd     = &vmstate_vmmouse,
     .qdev.no_user  = 1,
     .qdev.reset    = vmmouse_reset,
     .qdev.props = (Property[]) {
commit 43f20196716b68d334447c73e0221a6eacdfdb25
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Mar 21 10:52:24 2011 +0100

    vmmouse: Fix initialization
    
    Latest refactorings left vmmouse nonfunctional behind. Fix it by adding
    the required device initialization.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pc.c b/hw/pc.c
index 4d67d9f..6939c04 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1142,6 +1142,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     vmmouse = isa_try_create("vmmouse");
     if (vmmouse) {
         qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
+        qdev_init_nofail(&vmmouse->qdev);
     }
     port92 = isa_create_simple("port92");
     port92_init(port92, &a20_line[1]);
commit 663dc4e7bbda2527e5dbf45fb1e0ed2b5a92d806
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Mar 21 10:52:10 2011 +0100

    vmmouse: Fix typo preventing x86-64 build
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 59b7893..8895028 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -4,7 +4,7 @@ include pci.mak
 CONFIG_VGA_PCI=y
 CONFIG_VGA_ISA=y
 CONFIG_VMWARE_VGA=y
-CONFIG_VMMMOUSE=y
+CONFIG_VMMOUSE=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
 CONFIG_I8254=y
commit 7f90fa77b8f0dbe2e9d221953b8f9a6af6a3128a
Author: René Rebe <rene at exactcode.de>
Date:   Mon Mar 21 11:33:21 2011 +0100

    fix applesmc REV key
    
    Fix applesmc REV key string literal hex encoding.
    
    Signed-off-by: René Rebe <rene at exactcode.de>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/applesmc.c b/hw/applesmc.c
index 29b9330..23ed328 100644
--- a/hw/applesmc.c
+++ b/hw/applesmc.c
@@ -188,7 +188,7 @@ static void qdev_applesmc_isa_reset(DeviceState *dev)
         QLIST_REMOVE(d, node);
     }
 
-    applesmc_add_key(s, "REV ", 6, "\0x01\0x13\0x0f\0x00\0x00\0x03");
+    applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03");
     applesmc_add_key(s, "OSK0", 32, s->osk);
     applesmc_add_key(s, "OSK1", 32, s->osk + 32);
     applesmc_add_key(s, "NATJ", 1, "\0");
commit adf82011ef33df8e4d2421e957ccdbd5bbd12ad1
Author: René Rebe <rene at exactcode.de>
Date:   Mon Mar 21 11:18:50 2011 +0100

    enable kvm for ppc(32) on ppc64
    
    ppc64 is backward compatible, likewise.
    
    Signed-off-by: René Rebe <rene at exactcode.de>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index b523a6e..f594bfe 100755
--- a/configure
+++ b/configure
@@ -3124,6 +3124,8 @@ case "$target_arch2" in
       \( "$target_arch2" = "$cpu" -o \
       \( "$target_arch2" = "ppcemb" -a "$cpu" = "ppc" \) -o \
       \( "$target_arch2" = "ppc64"  -a "$cpu" = "ppc" \) -o \
+      \( "$target_arch2" = "ppc"    -a "$cpu" = "ppc64" \) -o \
+      \( "$target_arch2" = "ppcemb" -a "$cpu" = "ppc64" \) -o \
       \( "$target_arch2" = "x86_64" -a "$cpu" = "i386"   \) -o \
       \( "$target_arch2" = "i386"   -a "$cpu" = "x86_64" \) \) ; then
       echo "CONFIG_KVM=y" >> $config_target_mak
commit a0e13900079915ccb9c9be0b2b0592afdaf74d7f
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Wed Mar 16 11:21:22 2011 +0100

    target-ppc: add support for 6 SPE instructions
    
    Add support for 6 SPE instructions: evmra, evmwsmi{a{a}}, evmwumi{a{a}}
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 89413c5..3d265e3 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6502,6 +6502,39 @@ GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
 /***                           SPE extension                               ***/
 /* Register moves */
 
+
+static inline void gen_evmra(DisasContext *ctx)
+{
+
+    if (unlikely(!ctx->spe_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_APU);
+        return;
+    }
+
+#if defined(TARGET_PPC64)
+    /* rD := rA */
+    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+
+    /* spe_acc := rA */
+    tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
+                   cpu_env,
+                   offsetof(CPUState, spe_acc));
+#else
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    /* tmp := rA_lo + rA_hi << 32 */
+    tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
+
+    /* spe_acc := tmp */
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_temp_free_i64(tmp);
+
+    /* rD := rA */
+    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
+#endif
+}
+
 static inline void gen_load_gpr64(TCGv_i64 t, int reg)
 {
 #if defined(TARGET_PPC64)
@@ -7090,6 +7123,163 @@ static void gen_evsel3(DisasContext *ctx)
     gen_evsel(ctx);
 }
 
+/* Multiply */
+
+static inline void gen_evmwumi(DisasContext *ctx)
+{
+    TCGv_i64 t0, t1;
+
+    if (unlikely(!ctx->spe_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_APU);
+        return;
+    }
+
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+
+    /* t0 := rA; t1 := rB */
+#if defined(TARGET_PPC64)
+    tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
+    tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
+#else
+    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
+    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
+#endif
+
+    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
+
+    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+static inline void gen_evmwumia(DisasContext *ctx)
+{
+    TCGv_i64 tmp;
+
+    if (unlikely(!ctx->spe_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_APU);
+        return;
+    }
+
+    gen_evmwumi(ctx);            /* rD := rA * rB */
+
+    tmp = tcg_temp_new_i64();
+
+    /* acc := rD */
+    gen_load_gpr64(tmp, rD(ctx->opcode));
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+    tcg_temp_free_i64(tmp);
+}
+
+static inline void gen_evmwumiaa(DisasContext *ctx)
+{
+    TCGv_i64 acc;
+    TCGv_i64 tmp;
+
+    if (unlikely(!ctx->spe_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_APU);
+        return;
+    }
+
+    gen_evmwumi(ctx);           /* rD := rA * rB */
+
+    acc = tcg_temp_new_i64();
+    tmp = tcg_temp_new_i64();
+
+    /* tmp := rD */
+    gen_load_gpr64(tmp, rD(ctx->opcode));
+
+    /* Load acc */
+    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+
+    /* acc := tmp + acc */
+    tcg_gen_add_i64(acc, acc, tmp);
+
+    /* Store acc */
+    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+
+    /* rD := acc */
+    gen_store_gpr64(rD(ctx->opcode), acc);
+
+    tcg_temp_free_i64(acc);
+    tcg_temp_free_i64(tmp);
+}
+
+static inline void gen_evmwsmi(DisasContext *ctx)
+{
+    TCGv_i64 t0, t1;
+
+    if (unlikely(!ctx->spe_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_APU);
+        return;
+    }
+
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+
+    /* t0 := rA; t1 := rB */
+#if defined(TARGET_PPC64)
+    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
+    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
+#else
+    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
+    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
+#endif
+
+    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
+
+    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+}
+
+static inline void gen_evmwsmia(DisasContext *ctx)
+{
+    TCGv_i64 tmp;
+
+    gen_evmwsmi(ctx);            /* rD := rA * rB */
+
+    tmp = tcg_temp_new_i64();
+
+    /* acc := rD */
+    gen_load_gpr64(tmp, rD(ctx->opcode));
+    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
+
+    tcg_temp_free_i64(tmp);
+}
+
+static inline void gen_evmwsmiaa(DisasContext *ctx)
+{
+    TCGv_i64 acc = tcg_temp_new_i64();
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    gen_evmwsmi(ctx);           /* rD := rA * rB */
+
+    acc = tcg_temp_new_i64();
+    tmp = tcg_temp_new_i64();
+
+    /* tmp := rD */
+    gen_load_gpr64(tmp, rD(ctx->opcode));
+
+    /* Load acc */
+    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+
+    /* acc := tmp + acc */
+    tcg_gen_add_i64(acc, acc, tmp);
+
+    /* Store acc */
+    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
+
+    /* rD := acc */
+    gen_store_gpr64(rD(ctx->opcode), acc);
+
+    tcg_temp_free_i64(acc);
+    tcg_temp_free_i64(tmp);
+}
+
 GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
 GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
@@ -7098,10 +7288,14 @@ GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
 GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
 GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
 GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
+GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE);
 GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
 GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
@@ -7491,14 +7685,12 @@ GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
 
 GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
@@ -7506,7 +7698,6 @@ GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
 GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
 GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
 GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
-GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
 
 GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
@@ -7524,7 +7715,6 @@ GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
 GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
 GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
-GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
 GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
 
 GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
@@ -8739,10 +8929,14 @@ GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE),
 GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE),
 GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE),
 GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE),
+GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE),
 GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE),
 GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE),
 GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE),
 GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE),
+GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE),
 GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE),
 GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE),
 GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE),
commit 59c9d9cf3f225c983931baafd1c98931428a7567
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 22 07:03:15 2011 +0100

    pc-bios: update linuxboot.bin and multiboot.bin
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/pc-bios/linuxboot.bin b/pc-bios/linuxboot.bin
index d8f0ea8..e7c3669 100644
Binary files a/pc-bios/linuxboot.bin and b/pc-bios/linuxboot.bin differ
diff --git a/pc-bios/multiboot.bin b/pc-bios/multiboot.bin
index d7da6e0..f74a6e1 100644
Binary files a/pc-bios/multiboot.bin and b/pc-bios/multiboot.bin differ
commit 75b9f69057b166876a0c33d5fd86aa59ccfd3812
Author: Gleb Natapov <gleb at redhat.com>
Date:   Mon Jan 31 15:11:01 2011 +0200

    fix linuxboot.bin and multiboot.bin to not hijack int19
    
    Currently linuxboot.bin and multiboot.bin option roms override int19
    vector to intercept boot process. No sane option rom should do that.
    Provide bev entry instead that will be called by BIOS if option rom
    is selected for booting.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/pc-bios/optionrom/linuxboot.S b/pc-bios/optionrom/linuxboot.S
index c109363..748c831 100644
--- a/pc-bios/optionrom/linuxboot.S
+++ b/pc-bios/optionrom/linuxboot.S
@@ -22,6 +22,8 @@
 
 #include "optionrom.h"
 
+#define BOOT_ROM_PRODUCT "Linux loader"
+
 BOOT_ROM_START
 
 run_linuxboot:
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index 9131837..cc5ca1b 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -20,6 +20,8 @@
 
 #include "optionrom.h"
 
+#define BOOT_ROM_PRODUCT "multiboot loader"
+
 #define MULTIBOOT_MAGIC		0x2badb002
 
 #define GS_PROT_JUMP		0
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index fbdd48a..aa783de 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -97,22 +97,28 @@
 
 #define BOOT_ROM_START					\
 	OPTION_ROM_START				\
-	push		%eax;				\
-	push		%ds;				\
-							\
-	/* setup ds so we can access the IVT */		\
-	xor		%ax, %ax;			\
-	mov		%ax, %ds;			\
-							\
-	/* install our int 19 handler */		\
-	movw		$int19_handler, (0x19*4);	\
-	mov		%cs, (0x19*4+2);		\
-							\
-	pop		%ds;				\
-	pop		%eax;				\
 	lret;						\
-							\
-    int19_handler:;					\
+	.org 		0x18;				\
+	.short		0;				\
+	.short		_pnph;				\
+    _pnph:						\
+	.ascii		"$PnP";				\
+	.byte		0x01;				\
+	.byte		( _pnph_len / 16 );		\
+	.short		0x0000;				\
+	.byte		0x00;				\
+	.byte		0x00;				\
+	.long		0x00000000;			\
+	.short		_manufacturer;			\
+	.short		_product;			\
+	.long		0x00000000;			\
+	.short		0x0000;				\
+	.short		0x0000;				\
+	.short		_bev;				\
+	.short		0x0000;				\
+	.short		0x0000;				\
+	.equ		_pnph_len, . - _pnph;		\
+    _bev:;						\
 	/* DS = CS */					\
 	movw		%cs, %ax;			\
 	movw		%ax, %ds;
@@ -122,5 +128,9 @@
     _end:
 
 #define BOOT_ROM_END					\
+    _manufacturer:;					\
+	.asciz "QEMU";					\
+    _product:;						\
+	.asciz BOOT_ROM_PRODUCT;			\
 	OPTION_ROM_END
 
commit 31b7c261a207e1e670d737ec78a87dd031bd8f73
Merge: 8b06c62... dc7a09c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 21 17:42:20 2011 -0500

    Merge remote branch 'qemu-kvm/uq/master' into staging

diff --cc osdep.h
index 5e48860,748df54..970d767
--- a/osdep.h
+++ b/osdep.h
@@@ -128,22 -130,6 +128,23 @@@ void qemu_vfree(void *ptr)
  int qemu_madvise(void *addr, size_t len, int advice);
  
  int qemu_create_pidfile(const char *filename);
+ int qemu_get_thread_id(void);
  
 +#ifdef _WIN32
 +static inline void qemu_timersub(const struct timeval *val1,
 +                                 const struct timeval *val2,
 +                                 struct timeval *res)
 +{
 +    res->tv_sec = val1->tv_sec - val2->tv_sec;
 +    if (val1->tv_usec < val2->tv_usec) {
 +        res->tv_sec--;
 +        res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000;
 +    } else {
 +        res->tv_usec = val1->tv_usec - val2->tv_usec;
 +    }
 +}
 +#else
 +#define qemu_timersub timersub
 +#endif
 +
  #endif
commit 8b06c62ae48b67b320f7420dcd4854c5559e1532
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 15 11:22:12 2011 -0500

    seabios: update to latest git
    
     - cc97564 Add config option to permit running option roms with bad checksums.
     - 424f217 Add config option to disable MTRR initialization.
     - fb2f10d Prep version for next release.
     - f18b09b Update version to 0.6.2
     - 20fcf9b lets pretend that RTC can be used to wakeup from S4
     - 1efb10b Expand user configurable parameters in Kconfig.
     - 3dba4c2 Support non-local build directory - allow "make OUT=abc/" to work.
     - 42d9771 The vgabios build must depend on autoconf.h.
     - 32aa9f3 fix parallel compilation of SeaBIOS
     - 713be89 Start using Kconfig to configure SeaBIOS settings.
     - b623e7c Change kconfig to emit disabled symbols in autoconf.h.
     - 0da7bfd Build changes for Linux kconfig code to work in seabios dir structure.
     - a4c5daf Initial commit of Kconfig build tool.
     - 4d0c592 Minor boot fixes.
     - 812478e Minor comment / code layout improvement to romlayout.S.
     - 6fc7cf1 Fix to prevent infinite loop in build_pci_path().
     - f5154e2 support T13 EDD3.0 spec
     - d08eb9c Add ability to track PCI paths and add to build_pci_path().
     - 89a1efd Move the CBFS payload setup to later in the boot.
     - 9e881a3 Extract space trimming code from ATA and use in USB and bootorder code.
     - 3c241ed seabios: acpi: add _RMV control method for PCI devices
     - c2002a1 Add support for finding the boot priority of USB drives.
     - a5f2b91 Extend 'usb_pipe' to track the controller and ports of each device.
     - 8bf5503 Add functions for boot device path parsing.
     - c4bd3b9 Use bootprio_find_named_rom() for ramdisk and cbfs payload priorities.
     - ca2bc1c Remove drive->desc field.
     - f13a180 Minor reorganization of some of the boot_xxx code in boot.c.
     - 3da2c1c Move IPL.fw_bootorder to static variables in boot.c.
     - 7bb1584 Move IPL.bev to static variables in boot.c
     - baaadb6 Move IPL.checkfloppysig to a global (CheckFloppySig) in boot.c.
     - a0842f8 Remove Drives global struct in favor of independent global variables.
     - ecbcf77 Don't access drive_g->desc from boot_cdrom().
     - 551caa2 Simplify keyboard reading code in the interactive boot menu.
     - 697e63c Call setup_translation() from map_hd_drive().
     - 3c5e0e1 Rename add_ordered_drive() to add_drive() and use in map_hd_drive().
     - 031ef55 Add stubs to permit devices to specify their boot priority.
     - 72eee3e Simplify boot ordering by building an inclusive boot list.
     - ce24be5 Populate drive_g->desc prior to calling add_bcv_internal().
     - 74fd942 pciinit: fix off-by-one
     - 311f887 Minor build fixes.
     - bca3a87 Track the source of each optionrom deployed.
     - c6629e0 Support qemu based romfile wrappers called out of order.
     - d1a1746 Breakup boot_setup() bootorder code into its own function.
     - f9b0930 Add romfile_loadfile() helper function.
     - b9a7591 Read bootorder file into memory.
     - 2e109a6 Add strchr() function.
     - 1703ea2 Add romfile_name() function.
     - b674152 Add BAID for ahci cdrom.
     - f77e179 Provide full EDD 3.0 info for virtio disk
     - 67863be Enhance layoutrom.py to work around a binutils quirk.
     - 4c90a20 Create separate IPL entry for each CD/DVD
     - 0e6f636 ahci: set controller id
     - 1e924bb ahci: fix off-by-one in port count
     - 7eb0222 ahci: enable io/mem/dma
     - c19fc71 ahci: set dma feature flag
     - 80c2b6e Check if capability enabled in XXX_cmd_data functions.
     - f3fe3aa Require a "_cfuncXX_" symbol prefix for inter-mode c function references.
     - d52fdf6 add ahci support
     - 54fa8ec ata: make helpers available
     - 0a80608 util: add memset_fl()
     - f1f18eb pci: add helper functions for mmio bar access from real mode.
     - af9629b Enhance call32() to pass a parameter to called function.
     - 4057f98 Don't pass return address to transition(32,16,16big) on stack.
     - e2623fc pciinit: use pci_region functions.
     - 58a38e8 pci: introduce pci_region to manage pci io/memory/prefmemory regions.
     - 6d5a217 mark irq9 active high in DSDT
     - 9433098 Report meaningful error if pyserial not present in tools/readserial.py
     - 94dc9c4 Show size of non-relocatable runtime code during build.
     - 4d96edc Cleanup - it's no longer necessary to manually reset global variables.
     - a899945 Allow rom to grow to 256K.
     - 4a446d7 Fix typo preventing relocated space from being used for option roms.
     - 0f67397 fix virtio-blk failure after reboot
     - d4bded4 Add a debug method to AML code.
     - 2f96800 Warn that ohci bulk is not supported.
     - e826465 Enable optionroms to use freed space due to CONFIG_RELOCATE_INIT.
     - 7f55fd3 Move the 32bit init code to high memory at runtime.
     - 025cabd Move init code from _start() to post().
     - 12fa24a Add memalign_tmp() helper function.
     - 244caf8 Try to hard-reboot on rerun of post even on emulators.
     - 5bd01de Don't do shadow copying of optionroms when CONFIG_OPTIONROMS_DEPLOYED.
     - adaf373 Try to hard-reboot processor on rerun of post under coreboot.
     - 402fd9c Enhance build to emit relocation information.
     - d1b4f96 Separate out init code from the rest of the 32bit flat code.
     - 1a4885e Modify tools/layoutrom.py to use classes instead of tuples.
     - 6c2e781 Use str.startswith() in python scripts.
     - d9c916e Prep version for next release.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index e191908..bdb4831 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 06d0bdd..cc97564 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4
+Subproject commit cc975646af69f279396d4d5e1379ac6af80ee637
commit b784421ce4cc860315f4ec31bbc3d67e91984074
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Mar 15 15:53:25 2011 +0100

    Fix migration uint8 arrys handled
    
    commit 82fa39b75181b730d6d4d09f443bd26bcfcd045c
    
    only contains half of the fix.  It forgots the save state fix for
    UINT8 indexes.
    
    Anthony, please apply, without this migration using hpet is broken.
    (only current user).
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 388bf6f..03fce62 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1395,6 +1395,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                 n_elems = *(int32_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT16) {
                 n_elems = *(uint16_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT8) {
+                n_elems = *(uint8_t *)(opaque+field->num_offset);
             }
             if (field->flags & VMS_POINTER) {
                 base_addr = *(void **)base_addr + field->start;
commit bb98fe42c5c0516cae3a7378f3d7ba8e86297678
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon Mar 7 01:34:06 2011 +0100

    softfloat: Drop [s]bits{8, 16, 32, 64} types in favor of [u]int{8, 16, 32, 64}_t
    
    They are defined with the same semantics as the POSIX types,
    so prefer those for consistency. Suggested by Peter Maydell.
    
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index 54c0bad..3128e60 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -44,9 +44,9 @@ these four paragraphs for those parts of this code that are retained.
 | The result is stored in the location pointed to by `zPtr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
+INLINE void shift32RightJamming( uint32_t a, int16 count, uint32_t *zPtr )
 {
-    bits32 z;
+    uint32_t z;
 
     if ( count == 0 ) {
         z = a;
@@ -70,9 +70,9 @@ INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
 | The result is stored in the location pointed to by `zPtr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
+INLINE void shift64RightJamming( uint64_t a, int16 count, uint64_t *zPtr )
 {
-    bits64 z;
+    uint64_t z;
 
     if ( count == 0 ) {
         z = a;
@@ -106,9 +106,9 @@ INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
 
 INLINE void
  shift64ExtraRightJamming(
-     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
-    bits64 z0, z1;
+    uint64_t z0, z1;
     int8 negCount = ( - count ) & 63;
 
     if ( count == 0 ) {
@@ -143,9 +143,9 @@ INLINE void
 
 INLINE void
  shift128Right(
-     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
-    bits64 z0, z1;
+    uint64_t z0, z1;
     int8 negCount = ( - count ) & 63;
 
     if ( count == 0 ) {
@@ -178,9 +178,9 @@ INLINE void
 
 INLINE void
  shift128RightJamming(
-     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
-    bits64 z0, z1;
+    uint64_t z0, z1;
     int8 negCount = ( - count ) & 63;
 
     if ( count == 0 ) {
@@ -229,16 +229,16 @@ INLINE void
 
 INLINE void
  shift128ExtraRightJamming(
-     bits64 a0,
-     bits64 a1,
-     bits64 a2,
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t a2,
      int16 count,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr
  )
 {
-    bits64 z0, z1, z2;
+    uint64_t z0, z1, z2;
     int8 negCount = ( - count ) & 63;
 
     if ( count == 0 ) {
@@ -287,7 +287,7 @@ INLINE void
 
 INLINE void
  shortShift128Left(
-     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
 
     *z1Ptr = a1<<count;
@@ -306,16 +306,16 @@ INLINE void
 
 INLINE void
  shortShift192Left(
-     bits64 a0,
-     bits64 a1,
-     bits64 a2,
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t a2,
      int16 count,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr
  )
 {
-    bits64 z0, z1, z2;
+    uint64_t z0, z1, z2;
     int8 negCount;
 
     z2 = a2<<count;
@@ -341,9 +341,9 @@ INLINE void
 
 INLINE void
  add128(
-     bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
-    bits64 z1;
+    uint64_t z1;
 
     z1 = a1 + b1;
     *z1Ptr = z1;
@@ -361,18 +361,18 @@ INLINE void
 
 INLINE void
  add192(
-     bits64 a0,
-     bits64 a1,
-     bits64 a2,
-     bits64 b0,
-     bits64 b1,
-     bits64 b2,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t a2,
+     uint64_t b0,
+     uint64_t b1,
+     uint64_t b2,
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr
  )
 {
-    bits64 z0, z1, z2;
+    uint64_t z0, z1, z2;
     int8 carry0, carry1;
 
     z2 = a2 + b2;
@@ -399,7 +399,7 @@ INLINE void
 
 INLINE void
  sub128(
-     bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+     uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
 
     *z1Ptr = a1 - b1;
@@ -417,18 +417,18 @@ INLINE void
 
 INLINE void
  sub192(
-     bits64 a0,
-     bits64 a1,
-     bits64 a2,
-     bits64 b0,
-     bits64 b1,
-     bits64 b2,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t a2,
+     uint64_t b0,
+     uint64_t b1,
+     uint64_t b2,
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr
  )
 {
-    bits64 z0, z1, z2;
+    uint64_t z0, z1, z2;
     int8 borrow0, borrow1;
 
     z2 = a2 - b2;
@@ -451,21 +451,21 @@ INLINE void
 | `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
+INLINE void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
-    bits32 aHigh, aLow, bHigh, bLow;
-    bits64 z0, zMiddleA, zMiddleB, z1;
+    uint32_t aHigh, aLow, bHigh, bLow;
+    uint64_t z0, zMiddleA, zMiddleB, z1;
 
     aLow = a;
     aHigh = a>>32;
     bLow = b;
     bHigh = b>>32;
-    z1 = ( (bits64) aLow ) * bLow;
-    zMiddleA = ( (bits64) aLow ) * bHigh;
-    zMiddleB = ( (bits64) aHigh ) * bLow;
-    z0 = ( (bits64) aHigh ) * bHigh;
+    z1 = ( (uint64_t) aLow ) * bLow;
+    zMiddleA = ( (uint64_t) aLow ) * bHigh;
+    zMiddleB = ( (uint64_t) aHigh ) * bLow;
+    z0 = ( (uint64_t) aHigh ) * bHigh;
     zMiddleA += zMiddleB;
-    z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
+    z0 += ( ( (uint64_t) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
     zMiddleA <<= 32;
     z1 += zMiddleA;
     z0 += ( z1 < zMiddleA );
@@ -483,15 +483,15 @@ INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
 
 INLINE void
  mul128By64To192(
-     bits64 a0,
-     bits64 a1,
-     bits64 b,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t b,
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr
  )
 {
-    bits64 z0, z1, z2, more1;
+    uint64_t z0, z1, z2, more1;
 
     mul64To128( a1, b, &z1, &z2 );
     mul64To128( a0, b, &z0, &more1 );
@@ -511,18 +511,18 @@ INLINE void
 
 INLINE void
  mul128To256(
-     bits64 a0,
-     bits64 a1,
-     bits64 b0,
-     bits64 b1,
-     bits64 *z0Ptr,
-     bits64 *z1Ptr,
-     bits64 *z2Ptr,
-     bits64 *z3Ptr
+     uint64_t a0,
+     uint64_t a1,
+     uint64_t b0,
+     uint64_t b1,
+     uint64_t *z0Ptr,
+     uint64_t *z1Ptr,
+     uint64_t *z2Ptr,
+     uint64_t *z3Ptr
  )
 {
-    bits64 z0, z1, z2, z3;
-    bits64 more1, more2;
+    uint64_t z0, z1, z2, z3;
+    uint64_t more1, more2;
 
     mul64To128( a1, b1, &z2, &z3 );
     mul64To128( a1, b0, &z1, &more2 );
@@ -548,18 +548,18 @@ INLINE void
 | unsigned integer is returned.
 *----------------------------------------------------------------------------*/
 
-static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
+static uint64_t estimateDiv128To64( uint64_t a0, uint64_t a1, uint64_t b )
 {
-    bits64 b0, b1;
-    bits64 rem0, rem1, term0, term1;
-    bits64 z;
+    uint64_t b0, b1;
+    uint64_t rem0, rem1, term0, term1;
+    uint64_t z;
 
     if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
     b0 = b>>32;
     z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
     mul64To128( b, z, &term0, &term1 );
     sub128( a0, a1, term0, term1, &rem0, &rem1 );
-    while ( ( (sbits64) rem0 ) < 0 ) {
+    while ( ( (int64_t) rem0 ) < 0 ) {
         z -= LIT64( 0x100000000 );
         b1 = b<<32;
         add128( rem0, rem1, b0, b1, &rem0, &rem1 );
@@ -580,18 +580,18 @@ static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
 | value.
 *----------------------------------------------------------------------------*/
 
-static bits32 estimateSqrt32( int16 aExp, bits32 a )
+static uint32_t estimateSqrt32( int16 aExp, uint32_t a )
 {
-    static const bits16 sqrtOddAdjustments[] = {
+    static const uint16_t sqrtOddAdjustments[] = {
         0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
         0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
     };
-    static const bits16 sqrtEvenAdjustments[] = {
+    static const uint16_t sqrtEvenAdjustments[] = {
         0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
         0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
     };
     int8 index;
-    bits32 z;
+    uint32_t z;
 
     index = ( a>>27 ) & 15;
     if ( aExp & 1 ) {
@@ -603,9 +603,9 @@ static bits32 estimateSqrt32( int16 aExp, bits32 a )
         z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ (int)index ];
         z = a / z + z;
         z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
-        if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
+        if ( z <= a ) return (uint32_t) ( ( (int32_t) a )>>1 );
     }
-    return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
+    return ( (uint32_t) ( ( ( (uint64_t) a )<<31 ) / z ) ) + ( z>>1 );
 
 }
 
@@ -614,7 +614,7 @@ static bits32 estimateSqrt32( int16 aExp, bits32 a )
 | `a'.  If `a' is zero, 32 is returned.
 *----------------------------------------------------------------------------*/
 
-static int8 countLeadingZeros32( bits32 a )
+static int8 countLeadingZeros32( uint32_t a )
 {
     static const int8 countLeadingZerosHigh[] = {
         8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -655,12 +655,12 @@ static int8 countLeadingZeros32( bits32 a )
 | `a'.  If `a' is zero, 64 is returned.
 *----------------------------------------------------------------------------*/
 
-static int8 countLeadingZeros64( bits64 a )
+static int8 countLeadingZeros64( uint64_t a )
 {
     int8 shiftCount;
 
     shiftCount = 0;
-    if ( a < ( (bits64) 1 )<<32 ) {
+    if ( a < ( (uint64_t) 1 )<<32 ) {
         shiftCount += 32;
     }
     else {
@@ -677,7 +677,7 @@ static int8 countLeadingZeros64( bits64 a )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+INLINE flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 == b0 ) && ( a1 == b1 );
@@ -690,7 +690,7 @@ INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+INLINE flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
@@ -703,7 +703,7 @@ INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
 | returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+INLINE flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
@@ -716,7 +716,7 @@ INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+INLINE flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 != b0 ) || ( a1 != b1 );
diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c
index 008bb53..50355a4 100644
--- a/fpu/softfloat-native.c
+++ b/fpu/softfloat-native.c
@@ -418,7 +418,7 @@ int float64_is_quiet_nan( float64 a1 )
     u.f = a1;
     a = u.i;
 
-    return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) );
+    return ( LIT64( 0xFFF0000000000000 ) < (uint64_t) ( a<<1 ) );
 
 }
 
@@ -500,7 +500,7 @@ int floatx80_is_signaling_nan( floatx80 a1)
     aLow = u.i.low & ~ LIT64( 0x4000000000000000 );
     return
            ( ( u.i.high & 0x7FFF ) == 0x7FFF )
-        && (bits64) ( aLow<<1 )
+        && (uint64_t) ( aLow<<1 )
         && ( u.i.low == aLow );
 }
 
@@ -508,7 +508,7 @@ int floatx80_is_quiet_nan( floatx80 a1 )
 {
     floatx80u u;
     u.f = a1;
-    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
+    return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 );
 }
 
 #endif
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 4add93c..4b65de6 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -52,7 +52,7 @@ void float_raise( int8 flags STATUS_PARAM )
 *----------------------------------------------------------------------------*/
 typedef struct {
     flag sign;
-    bits64 high, low;
+    uint64_t high, low;
 } commonNaNT;
 
 /*----------------------------------------------------------------------------
@@ -120,7 +120,7 @@ static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
     if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
     z.sign = float16_val(a) >> 15;
     z.low = 0;
-    z.high = ((bits64) float16_val(a))<<54;
+    z.high = ((uint64_t) float16_val(a))<<54;
     return z;
 }
 
@@ -156,7 +156,7 @@ int float32_is_quiet_nan( float32 a_ )
 #if SNAN_BIT_IS_ONE
     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
 #else
-    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
+    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
 #endif
 }
 
@@ -169,7 +169,7 @@ int float32_is_signaling_nan( float32 a_ )
 {
     uint32_t a = float32_val(a_);
 #if SNAN_BIT_IS_ONE
-    return ( 0xFF800000 <= (bits32) ( a<<1 ) );
+    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
 #else
     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
 #endif
@@ -190,7 +190,7 @@ float32 float32_maybe_silence_nan( float32 a_ )
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
 #else
-        bits32 a = float32_val(a_);
+        uint32_t a = float32_val(a_);
         a |= (1 << 22);
         return make_float32(a);
 #endif
@@ -211,7 +211,7 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
     z.sign = float32_val(a)>>31;
     z.low = 0;
-    z.high = ( (bits64) float32_val(a) )<<41;
+    z.high = ( (uint64_t) float32_val(a) )<<41;
     return z;
 }
 
@@ -222,7 +222,7 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
 
 static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
 {
-    bits32 mantissa = a.high>>41;
+    uint32_t mantissa = a.high>>41;
 
     if ( STATUS(default_nan_mode) ) {
         return float32_default_nan;
@@ -230,7 +230,7 @@ static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
 
     if ( mantissa )
         return make_float32(
-            ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
+            ( ( (uint32_t) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
     else
         return float32_default_nan;
 }
@@ -357,7 +357,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 {
     flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
-    bits32 av, bv;
+    uint32_t av, bv;
 
     aIsQuietNaN = float32_is_quiet_nan( a );
     aIsSignalingNaN = float32_is_signaling_nan( a );
@@ -371,9 +371,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
     if ( STATUS(default_nan_mode) )
         return float32_default_nan;
 
-    if ((bits32)(av<<1) < (bits32)(bv<<1)) {
+    if ((uint32_t)(av<<1) < (uint32_t)(bv<<1)) {
         aIsLargerSignificand = 0;
-    } else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
+    } else if ((uint32_t)(bv<<1) < (uint32_t)(av<<1)) {
         aIsLargerSignificand = 1;
     } else {
         aIsLargerSignificand = (av < bv) ? 1 : 0;
@@ -394,13 +394,13 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 
 int float64_is_quiet_nan( float64 a_ )
 {
-    bits64 a = float64_val(a_);
+    uint64_t a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
     return
            ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
         && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
 #else
-    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
+    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
 #endif
 }
 
@@ -411,9 +411,9 @@ int float64_is_quiet_nan( float64 a_ )
 
 int float64_is_signaling_nan( float64 a_ )
 {
-    bits64 a = float64_val(a_);
+    uint64_t a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
-    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
+    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
 #else
     return
            ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
@@ -436,7 +436,7 @@ float64 float64_maybe_silence_nan( float64 a_ )
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
 #else
-        bits64 a = float64_val(a_);
+        uint64_t a = float64_val(a_);
         a |= LIT64( 0x0008000000000000 );
         return make_float64(a);
 #endif
@@ -468,7 +468,7 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
 
 static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
 {
-    bits64 mantissa = a.high>>12;
+    uint64_t mantissa = a.high>>12;
 
     if ( STATUS(default_nan_mode) ) {
         return float64_default_nan;
@@ -476,7 +476,7 @@ static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
 
     if ( mantissa )
         return make_float64(
-              ( ( (bits64) a.sign )<<63 )
+              ( ( (uint64_t) a.sign )<<63 )
             | LIT64( 0x7FF0000000000000 )
             | ( a.high>>12 ));
     else
@@ -493,7 +493,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 {
     flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
-    bits64 av, bv;
+    uint64_t av, bv;
 
     aIsQuietNaN = float64_is_quiet_nan( a );
     aIsSignalingNaN = float64_is_signaling_nan( a );
@@ -507,9 +507,9 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
     if ( STATUS(default_nan_mode) )
         return float64_default_nan;
 
-    if ((bits64)(av<<1) < (bits64)(bv<<1)) {
+    if ((uint64_t)(av<<1) < (uint64_t)(bv<<1)) {
         aIsLargerSignificand = 0;
-    } else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
+    } else if ((uint64_t)(bv<<1) < (uint64_t)(av<<1)) {
         aIsLargerSignificand = 1;
     } else {
         aIsLargerSignificand = (av < bv) ? 1 : 0;
@@ -534,16 +534,16 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 int floatx80_is_quiet_nan( floatx80 a )
 {
 #if SNAN_BIT_IS_ONE
-    bits64 aLow;
+    uint64_t aLow;
 
     aLow = a.low & ~ LIT64( 0x4000000000000000 );
     return
            ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (bits64) ( aLow<<1 )
+        && (uint64_t) ( aLow<<1 )
         && ( a.low == aLow );
 #else
     return ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
+        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
 #endif
 }
 
@@ -557,14 +557,14 @@ int floatx80_is_signaling_nan( floatx80 a )
 {
 #if SNAN_BIT_IS_ONE
     return ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
+        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
 #else
-    bits64 aLow;
+    uint64_t aLow;
 
     aLow = a.low & ~ LIT64( 0x4000000000000000 );
     return
            ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (bits64) ( aLow<<1 )
+        && (uint64_t) ( aLow<<1 )
         && ( a.low == aLow );
 #endif
 }
@@ -628,7 +628,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
         z.low = a.high;
     else
         z.low = floatx80_default_nan_low;
-    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
+    z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
     return z;
 }
 
@@ -689,7 +689,7 @@ int float128_is_quiet_nan( float128 a )
         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
 #else
     return
-           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
+           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
 #endif
 }
@@ -703,7 +703,7 @@ int float128_is_signaling_nan( float128 a )
 {
 #if SNAN_BIT_IS_ONE
     return
-           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
+           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
 #else
     return
@@ -767,7 +767,7 @@ static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM)
     }
 
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
-    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
+    z.high |= ( ( (uint64_t) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
     return z;
 }
 
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e800daa..08e4ae0 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -109,7 +109,7 @@ INLINE flag extractFloat16Sign(float16 a)
 | positive or negative integer is returned.
 *----------------------------------------------------------------------------*/
 
-static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM)
+static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
 {
     int8 roundingMode;
     flag roundNearestEven;
@@ -140,7 +140,7 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM)
     if ( zSign ) z = - z;
     if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+        return zSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
     }
     if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
     return z;
@@ -159,7 +159,7 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ STATUS_PARAM)
 | returned.
 *----------------------------------------------------------------------------*/
 
-static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PARAM)
+static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATUS_PARAM)
 {
     int8 roundingMode;
     flag roundNearestEven, increment;
@@ -167,7 +167,7 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PA
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    increment = ( (sbits64) absZ1 < 0 );
+    increment = ( (int64_t) absZ1 < 0 );
     if ( ! roundNearestEven ) {
         if ( roundingMode == float_round_to_zero ) {
             increment = 0;
@@ -184,7 +184,7 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PA
     if ( increment ) {
         ++absZ0;
         if ( absZ0 == 0 ) goto overflow;
-        absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
+        absZ0 &= ~ ( ( (uint64_t) ( absZ1<<1 ) == 0 ) & roundNearestEven );
     }
     z = absZ0;
     if ( zSign ) z = - z;
@@ -192,7 +192,7 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PA
  overflow:
         float_raise( float_flag_invalid STATUS_VAR);
         return
-              zSign ? (sbits64) LIT64( 0x8000000000000000 )
+              zSign ? (int64_t) LIT64( 0x8000000000000000 )
             : LIT64( 0x7FFFFFFFFFFFFFFF );
     }
     if ( absZ1 ) STATUS(float_exception_flags) |= float_flag_inexact;
@@ -204,7 +204,7 @@ static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 STATUS_PA
 | Returns the fraction bits of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE bits32 extractFloat32Frac( float32 a )
+INLINE uint32_t extractFloat32Frac( float32 a )
 {
 
     return float32_val(a) & 0x007FFFFF;
@@ -256,7 +256,7 @@ static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
 *----------------------------------------------------------------------------*/
 
 static void
- normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
+ normalizeFloat32Subnormal( uint32_t aSig, int16 *zExpPtr, uint32_t *zSigPtr )
 {
     int8 shiftCount;
 
@@ -277,11 +277,11 @@ static void
 | significand.
 *----------------------------------------------------------------------------*/
 
-INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
+INLINE float32 packFloat32( flag zSign, int16 zExp, uint32_t zSig )
 {
 
     return make_float32(
-          ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig);
+          ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) + zSig);
 
 }
 
@@ -307,7 +307,7 @@ INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
 | Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
+static float32 roundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
 {
     int8 roundingMode;
     flag roundNearestEven;
@@ -332,10 +332,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P
         }
     }
     roundBits = zSig & 0x7F;
-    if ( 0xFD <= (bits16) zExp ) {
+    if ( 0xFD <= (uint16_t) zExp ) {
         if (    ( 0xFD < zExp )
              || (    ( zExp == 0xFD )
-                  && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
+                  && ( (int32_t) ( zSig + roundIncrement ) < 0 ) )
            ) {
             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
             return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
@@ -370,7 +370,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P
 *----------------------------------------------------------------------------*/
 
 static float32
- normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
 {
     int8 shiftCount;
 
@@ -383,7 +383,7 @@ static float32
 | Returns the fraction bits of the double-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE bits64 extractFloat64Frac( float64 a )
+INLINE uint64_t extractFloat64Frac( float64 a )
 {
 
     return float64_val(a) & LIT64( 0x000FFFFFFFFFFFFF );
@@ -435,7 +435,7 @@ static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
 *----------------------------------------------------------------------------*/
 
 static void
- normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
+ normalizeFloat64Subnormal( uint64_t aSig, int16 *zExpPtr, uint64_t *zSigPtr )
 {
     int8 shiftCount;
 
@@ -456,11 +456,11 @@ static void
 | significand.
 *----------------------------------------------------------------------------*/
 
-INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
+INLINE float64 packFloat64( flag zSign, int16 zExp, uint64_t zSig )
 {
 
     return make_float64(
-        ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig);
+        ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<52 ) + zSig);
 
 }
 
@@ -486,7 +486,7 @@ INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
 | Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
+static float64 roundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
 {
     int8 roundingMode;
     flag roundNearestEven;
@@ -511,10 +511,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P
         }
     }
     roundBits = zSig & 0x3FF;
-    if ( 0x7FD <= (bits16) zExp ) {
+    if ( 0x7FD <= (uint16_t) zExp ) {
         if (    ( 0x7FD < zExp )
              || (    ( zExp == 0x7FD )
-                  && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
+                  && ( (int64_t) ( zSig + roundIncrement ) < 0 ) )
            ) {
             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
             return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
@@ -549,7 +549,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P
 *----------------------------------------------------------------------------*/
 
 static float64
- normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
 {
     int8 shiftCount;
 
@@ -565,7 +565,7 @@ static float64
 | value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE bits64 extractFloatx80Frac( floatx80 a )
+INLINE uint64_t extractFloatx80Frac( floatx80 a )
 {
 
     return a.low;
@@ -604,7 +604,7 @@ INLINE flag extractFloatx80Sign( floatx80 a )
 *----------------------------------------------------------------------------*/
 
 static void
- normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
+ normalizeFloatx80Subnormal( uint64_t aSig, int32 *zExpPtr, uint64_t *zSigPtr )
 {
     int8 shiftCount;
 
@@ -619,12 +619,12 @@ static void
 | extended double-precision floating-point value, returning the result.
 *----------------------------------------------------------------------------*/
 
-INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
+INLINE floatx80 packFloatx80( flag zSign, int32 zExp, uint64_t zSig )
 {
     floatx80 z;
 
     z.low = zSig;
-    z.high = ( ( (bits16) zSign )<<15 ) + zExp;
+    z.high = ( ( (uint16_t) zSign )<<15 ) + zExp;
     return z;
 
 }
@@ -655,7 +655,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
 
 static floatx80
  roundAndPackFloatx80(
-     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+     int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1
  STATUS_PARAM)
 {
     int8 roundingMode;
@@ -692,7 +692,7 @@ static floatx80
         }
     }
     roundBits = zSig0 & roundMask;
-    if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+    if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
         if (    ( 0x7FFE < zExp )
              || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
            ) {
@@ -710,7 +710,7 @@ static floatx80
             if ( isTiny && roundBits ) float_raise( float_flag_underflow STATUS_VAR);
             if ( roundBits ) STATUS(float_exception_flags) |= float_flag_inexact;
             zSig0 += roundIncrement;
-            if ( (sbits64) zSig0 < 0 ) zExp = 1;
+            if ( (int64_t) zSig0 < 0 ) zExp = 1;
             roundIncrement = roundMask + 1;
             if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
                 roundMask |= roundIncrement;
@@ -733,7 +733,7 @@ static floatx80
     if ( zSig0 == 0 ) zExp = 0;
     return packFloatx80( zSign, zExp, zSig0 );
  precision80:
-    increment = ( (sbits64) zSig1 < 0 );
+    increment = ( (int64_t) zSig1 < 0 );
     if ( ! roundNearestEven ) {
         if ( roundingMode == float_round_to_zero ) {
             increment = 0;
@@ -747,7 +747,7 @@ static floatx80
             }
         }
     }
-    if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+    if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
         if (    ( 0x7FFE < zExp )
              || (    ( zExp == 0x7FFE )
                   && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
@@ -776,7 +776,7 @@ static floatx80
             if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR);
             if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
             if ( roundNearestEven ) {
-                increment = ( (sbits64) zSig1 < 0 );
+                increment = ( (int64_t) zSig1 < 0 );
             }
             else {
                 if ( zSign ) {
@@ -789,8 +789,8 @@ static floatx80
             if ( increment ) {
                 ++zSig0;
                 zSig0 &=
-                    ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
-                if ( (sbits64) zSig0 < 0 ) zExp = 1;
+                    ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+                if ( (int64_t) zSig0 < 0 ) zExp = 1;
             }
             return packFloatx80( zSign, zExp, zSig0 );
         }
@@ -803,7 +803,7 @@ static floatx80
             zSig0 = LIT64( 0x8000000000000000 );
         }
         else {
-            zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+            zSig0 &= ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
         }
     }
     else {
@@ -824,7 +824,7 @@ static floatx80
 
 static floatx80
  normalizeRoundAndPackFloatx80(
-     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+     int8 roundingPrecision, flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1
  STATUS_PARAM)
 {
     int8 shiftCount;
@@ -851,7 +851,7 @@ static floatx80
 | floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE bits64 extractFloat128Frac1( float128 a )
+INLINE uint64_t extractFloat128Frac1( float128 a )
 {
 
     return a.low;
@@ -863,7 +863,7 @@ INLINE bits64 extractFloat128Frac1( float128 a )
 | floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE bits64 extractFloat128Frac0( float128 a )
+INLINE uint64_t extractFloat128Frac0( float128 a )
 {
 
     return a.high & LIT64( 0x0000FFFFFFFFFFFF );
@@ -905,11 +905,11 @@ INLINE flag extractFloat128Sign( float128 a )
 
 static void
  normalizeFloat128Subnormal(
-     bits64 aSig0,
-     bits64 aSig1,
+     uint64_t aSig0,
+     uint64_t aSig1,
      int32 *zExpPtr,
-     bits64 *zSig0Ptr,
-     bits64 *zSig1Ptr
+     uint64_t *zSig0Ptr,
+     uint64_t *zSig1Ptr
  )
 {
     int8 shiftCount;
@@ -948,12 +948,12 @@ static void
 *----------------------------------------------------------------------------*/
 
 INLINE float128
- packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
+ packFloat128( flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 )
 {
     float128 z;
 
     z.low = zSig1;
-    z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
+    z.high = ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<48 ) + zSig0;
     return z;
 
 }
@@ -981,14 +981,14 @@ INLINE float128
 
 static float128
  roundAndPackFloat128(
-     flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 STATUS_PARAM)
+     flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1, uint64_t zSig2 STATUS_PARAM)
 {
     int8 roundingMode;
     flag roundNearestEven, increment, isTiny;
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    increment = ( (sbits64) zSig2 < 0 );
+    increment = ( (int64_t) zSig2 < 0 );
     if ( ! roundNearestEven ) {
         if ( roundingMode == float_round_to_zero ) {
             increment = 0;
@@ -1002,7 +1002,7 @@ static float128
             }
         }
     }
-    if ( 0x7FFD <= (bits32) zExp ) {
+    if ( 0x7FFD <= (uint32_t) zExp ) {
         if (    ( 0x7FFD < zExp )
              || (    ( zExp == 0x7FFD )
                   && eq128(
@@ -1046,7 +1046,7 @@ static float128
             zExp = 0;
             if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
             if ( roundNearestEven ) {
-                increment = ( (sbits64) zSig2 < 0 );
+                increment = ( (int64_t) zSig2 < 0 );
             }
             else {
                 if ( zSign ) {
@@ -1082,10 +1082,10 @@ static float128
 
 static float128
  normalizeRoundAndPackFloat128(
-     flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 STATUS_PARAM)
+     flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 STATUS_PARAM)
 {
     int8 shiftCount;
-    bits64 zSig2;
+    uint64_t zSig2;
 
     if ( zSig0 == 0 ) {
         zSig0 = zSig1;
@@ -1119,7 +1119,7 @@ float32 int32_to_float32( int32 a STATUS_PARAM )
     flag zSign;
 
     if ( a == 0 ) return float32_zero;
-    if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
+    if ( a == (int32_t) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
     zSign = ( a < 0 );
     return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR );
 
@@ -1136,7 +1136,7 @@ float64 int32_to_float64( int32 a STATUS_PARAM )
     flag zSign;
     uint32 absA;
     int8 shiftCount;
-    bits64 zSig;
+    uint64_t zSig;
 
     if ( a == 0 ) return float64_zero;
     zSign = ( a < 0 );
@@ -1161,7 +1161,7 @@ floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
     flag zSign;
     uint32 absA;
     int8 shiftCount;
-    bits64 zSig;
+    uint64_t zSig;
 
     if ( a == 0 ) return packFloatx80( 0, 0, 0 );
     zSign = ( a < 0 );
@@ -1187,7 +1187,7 @@ float128 int32_to_float128( int32 a STATUS_PARAM )
     flag zSign;
     uint32 absA;
     int8 shiftCount;
-    bits64 zSig0;
+    uint64_t zSig0;
 
     if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
     zSign = ( a < 0 );
@@ -1264,7 +1264,7 @@ float64 int64_to_float64( int64 a STATUS_PARAM )
     flag zSign;
 
     if ( a == 0 ) return float64_zero;
-    if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
+    if ( a == (int64_t) LIT64( 0x8000000000000000 ) ) {
         return packFloat64( 1, 0x43E, 0 );
     }
     zSign = ( a < 0 );
@@ -1318,7 +1318,7 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
     uint64 absA;
     int8 shiftCount;
     int32 zExp;
-    bits64 zSig0, zSig1;
+    uint64_t zSig0, zSig1;
 
     if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
     zSign = ( a < 0 );
@@ -1355,8 +1355,8 @@ int32 float32_to_int32( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits32 aSig;
-    bits64 aSig64;
+    uint32_t aSig;
+    uint64_t aSig64;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat32Frac( a );
@@ -1386,7 +1386,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits32 aSig;
+    uint32_t aSig;
     int32 z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
@@ -1399,7 +1399,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
             float_raise( float_flag_invalid STATUS_VAR);
             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
         }
-        return (sbits32) 0x80000000;
+        return (int32_t) 0x80000000;
     }
     else if ( aExp <= 0x7E ) {
         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
@@ -1407,7 +1407,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
     }
     aSig = ( aSig | 0x00800000 )<<8;
     z = aSig>>( - shiftCount );
-    if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+    if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
     }
     if ( aSign ) z = - z;
@@ -1429,7 +1429,7 @@ int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits32 aSig;
+    uint32_t aSig;
     int32 z;
 
     aSig = extractFloat32Frac( a );
@@ -1443,7 +1443,7 @@ int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
                 return 0x7FFF;
             }
         }
-        return (sbits32) 0xffff8000;
+        return (int32_t) 0xffff8000;
     }
     else if ( aExp <= 0x7E ) {
         if ( aExp | aSig ) {
@@ -1454,7 +1454,7 @@ int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
     shiftCount -= 0x10;
     aSig = ( aSig | 0x00800000 )<<8;
     z = aSig>>( - shiftCount );
-    if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+    if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
     }
     if ( aSign ) {
@@ -1478,8 +1478,8 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits32 aSig;
-    bits64 aSig64, aSigExtra;
+    uint32_t aSig;
+    uint64_t aSig64, aSigExtra;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -1491,7 +1491,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
         if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
             return LIT64( 0x7FFFFFFFFFFFFFFF );
         }
-        return (sbits64) LIT64( 0x8000000000000000 );
+        return (int64_t) LIT64( 0x8000000000000000 );
     }
     if ( aExp ) aSig |= 0x00800000;
     aSig64 = aSig;
@@ -1515,8 +1515,8 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits32 aSig;
-    bits64 aSig64;
+    uint32_t aSig;
+    uint64_t aSig64;
     int64 z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
@@ -1531,7 +1531,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
         }
-        return (sbits64) LIT64( 0x8000000000000000 );
+        return (int64_t) LIT64( 0x8000000000000000 );
     }
     else if ( aExp <= 0x7E ) {
         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
@@ -1540,7 +1540,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
     aSig64 = aSig | 0x00800000;
     aSig64 <<= 40;
     z = aSig64>>( - shiftCount );
-    if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) {
+    if ( (uint64_t) ( aSig64<<( shiftCount & 63 ) ) ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
     }
     if ( aSign ) z = - z;
@@ -1559,7 +1559,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -1574,7 +1574,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
         --aExp;
     }
-    return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
+    return packFloat64( aSign, aExp + 0x380, ( (uint64_t) aSig )<<29 );
 
 }
 
@@ -1591,7 +1591,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat32Frac( a );
@@ -1606,7 +1606,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
     }
     aSig |= 0x00800000;
-    return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
+    return packFloatx80( aSign, aExp + 0x3F80, ( (uint64_t) aSig )<<40 );
 
 }
 
@@ -1625,7 +1625,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat32Frac( a );
@@ -1640,7 +1640,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
         --aExp;
     }
-    return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 );
+    return packFloat128( aSign, aExp + 0x3F80, ( (uint64_t) aSig )<<25, 0 );
 
 }
 
@@ -1657,9 +1657,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
 {
     flag aSign;
     int16 aExp;
-    bits32 lastBitMask, roundBitsMask;
+    uint32_t lastBitMask, roundBitsMask;
     int8 roundingMode;
-    bits32 z;
+    uint32_t z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aExp = extractFloat32Exp( a );
@@ -1670,7 +1670,7 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
         return a;
     }
     if ( aExp <= 0x7E ) {
-        if ( (bits32) ( float32_val(a)<<1 ) == 0 ) return a;
+        if ( (uint32_t) ( float32_val(a)<<1 ) == 0 ) return a;
         STATUS(float_exception_flags) |= float_flag_inexact;
         aSign = extractFloat32Sign( a );
         switch ( STATUS(float_rounding_mode) ) {
@@ -1717,7 +1717,7 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
 static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
 {
     int16 aExp, bExp, zExp;
-    bits32 aSig, bSig, zSig;
+    uint32_t aSig, bSig, zSig;
     int16 expDiff;
 
     aSig = extractFloat32Frac( a );
@@ -1771,7 +1771,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
     aSig |= 0x20000000;
     zSig = ( aSig + bSig )<<1;
     --zExp;
-    if ( (sbits32) zSig < 0 ) {
+    if ( (int32_t) zSig < 0 ) {
         zSig = aSig + bSig;
         ++zExp;
     }
@@ -1791,7 +1791,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
 static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
 {
     int16 aExp, bExp, zExp;
-    bits32 aSig, bSig, zSig;
+    uint32_t aSig, bSig, zSig;
     int16 expDiff;
 
     aSig = extractFloat32Frac( a );
@@ -1911,9 +1911,9 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
-    bits32 aSig, bSig;
-    bits64 zSig64;
-    bits32 zSig;
+    uint32_t aSig, bSig;
+    uint64_t zSig64;
+    uint32_t zSig;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
@@ -1954,9 +1954,9 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
     zExp = aExp + bExp - 0x7F;
     aSig = ( aSig | 0x00800000 )<<7;
     bSig = ( bSig | 0x00800000 )<<8;
-    shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
+    shift64RightJamming( ( (uint64_t) aSig ) * bSig, 32, &zSig64 );
     zSig = zSig64;
-    if ( 0 <= (sbits32) ( zSig<<1 ) ) {
+    if ( 0 <= (int32_t) ( zSig<<1 ) ) {
         zSig <<= 1;
         --zExp;
     }
@@ -1974,7 +1974,7 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
-    bits32 aSig, bSig, zSig;
+    uint32_t aSig, bSig, zSig;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2020,9 +2020,9 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
         aSig >>= 1;
         ++zExp;
     }
-    zSig = ( ( (bits64) aSig )<<32 ) / bSig;
+    zSig = ( ( (uint64_t) aSig )<<32 ) / bSig;
     if ( ( zSig & 0x3F ) == 0 ) {
-        zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 );
+        zSig |= ( (uint64_t) bSig * zSig != ( (uint64_t) aSig )<<32 );
     }
     return roundAndPackFloat32( zSign, zExp, zSig STATUS_VAR );
 
@@ -2038,11 +2038,11 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, zSign;
     int16 aExp, bExp, expDiff;
-    bits32 aSig, bSig;
-    bits32 q;
-    bits64 aSig64, bSig64, q64;
-    bits32 alternateASig;
-    sbits32 sigMean;
+    uint32_t aSig, bSig;
+    uint32_t q;
+    uint64_t aSig64, bSig64, q64;
+    uint32_t alternateASig;
+    int32_t sigMean;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2086,7 +2086,7 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
         q = ( bSig <= aSig );
         if ( q ) aSig -= bSig;
         if ( 0 < expDiff ) {
-            q = ( ( (bits64) aSig )<<32 ) / bSig;
+            q = ( ( (uint64_t) aSig )<<32 ) / bSig;
             q >>= 32 - expDiff;
             bSig >>= 2;
             aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
@@ -2098,8 +2098,8 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
     }
     else {
         if ( bSig <= aSig ) aSig -= bSig;
-        aSig64 = ( (bits64) aSig )<<40;
-        bSig64 = ( (bits64) bSig )<<40;
+        aSig64 = ( (uint64_t) aSig )<<40;
+        bSig64 = ( (uint64_t) bSig )<<40;
         expDiff -= 64;
         while ( 0 < expDiff ) {
             q64 = estimateDiv128To64( aSig64, 0, bSig64 );
@@ -2118,12 +2118,12 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
         alternateASig = aSig;
         ++q;
         aSig -= bSig;
-    } while ( 0 <= (sbits32) aSig );
+    } while ( 0 <= (int32_t) aSig );
     sigMean = aSig + alternateASig;
     if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
         aSig = alternateASig;
     }
-    zSign = ( (sbits32) aSig < 0 );
+    zSign = ( (int32_t) aSig < 0 );
     if ( zSign ) aSig = - aSig;
     return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig STATUS_VAR );
 
@@ -2139,8 +2139,8 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, zExp;
-    bits32 aSig, zSig;
-    bits64 rem, term;
+    uint32_t aSig, zSig;
+    uint64_t rem, term;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -2170,11 +2170,11 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
             goto roundAndPack;
         }
         aSig >>= aExp & 1;
-        term = ( (bits64) zSig ) * zSig;
-        rem = ( ( (bits64) aSig )<<32 ) - term;
-        while ( (sbits64) rem < 0 ) {
+        term = ( (uint64_t) zSig ) * zSig;
+        rem = ( ( (uint64_t) aSig )<<32 ) - term;
+        while ( (int64_t) rem < 0 ) {
             --zSig;
-            rem += ( ( (bits64) zSig )<<1 ) | 1;
+            rem += ( ( (uint64_t) zSig )<<1 ) | 1;
         }
         zSig |= ( rem != 0 );
     }
@@ -2225,7 +2225,7 @@ float32 float32_exp2( float32 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
     float64 r, x, xn;
     int i;
     a = float32_squash_input_denormal(a STATUS_VAR);
@@ -2273,7 +2273,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
 {
     flag aSign, zSign;
     int16 aExp;
-    bits32 aSig, zSig, i;
+    uint32_t aSig, zSig, i;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat32Frac( a );
@@ -2299,7 +2299,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
     zSig = aExp << 23;
 
     for (i = 1 << 22; i > 0; i >>= 1) {
-        aSig = ( (bits64)aSig * aSig ) >> 23;
+        aSig = ( (uint64_t)aSig * aSig ) >> 23;
         if ( aSig & 0x01000000 ) {
             aSig >>= 1;
             zSig |= i;
@@ -2332,7 +2332,7 @@ int float32_eq( float32 a, float32 b STATUS_PARAM )
         return 0;
     }
     return ( float32_val(a) == float32_val(b) ) ||
-            ( (bits32) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
+            ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
 
 }
 
@@ -2346,7 +2346,7 @@ int float32_eq( float32 a, float32 b STATUS_PARAM )
 int float32_le( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits32 av, bv;
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2360,7 +2360,7 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
     bSign = extractFloat32Sign( b );
     av = float32_val(a);
     bv = float32_val(b);
-    if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 );
+    if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
     return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
@@ -2374,7 +2374,7 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
 int float32_lt( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits32 av, bv;
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2388,7 +2388,7 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
     bSign = extractFloat32Sign( b );
     av = float32_val(a);
     bv = float32_val(b);
-    if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 );
+    if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
     return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
@@ -2402,7 +2402,7 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
 
 int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
 {
-    bits32 av, bv;
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2414,7 +2414,7 @@ int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
     }
     av = float32_val(a);
     bv = float32_val(b);
-    return ( av == bv ) || ( (bits32) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -2428,7 +2428,7 @@ int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
 int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits32 av, bv;
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2444,7 +2444,7 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
     bSign = extractFloat32Sign( b );
     av = float32_val(a);
     bv = float32_val(b);
-    if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 );
+    if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
     return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
@@ -2459,7 +2459,7 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
 int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits32 av, bv;
+    uint32_t av, bv;
     a = float32_squash_input_denormal(a STATUS_VAR);
     b = float32_squash_input_denormal(b STATUS_VAR);
 
@@ -2475,7 +2475,7 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
     bSign = extractFloat32Sign( b );
     av = float32_val(a);
     bv = float32_val(b);
-    if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 );
+    if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
     return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
@@ -2494,7 +2494,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits64 aSig;
+    uint64_t aSig;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -2522,7 +2522,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits64 aSig, savedASig;
+    uint64_t aSig, savedASig;
     int32 z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
@@ -2546,7 +2546,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+        return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
@@ -2569,7 +2569,7 @@ int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits64 aSig, savedASig;
+    uint64_t aSig, savedASig;
     int32 z;
 
     aSig = extractFloat64Frac( a );
@@ -2598,7 +2598,7 @@ int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
     if ( ( (int16_t)z < 0 ) ^ aSign ) {
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return aSign ? (sbits32) 0xffff8000 : 0x7FFF;
+        return aSign ? (int32_t) 0xffff8000 : 0x7FFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
@@ -2620,7 +2620,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits64 aSig, aSigExtra;
+    uint64_t aSig, aSigExtra;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -2637,7 +2637,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
                ) {
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
-            return (sbits64) LIT64( 0x8000000000000000 );
+            return (int64_t) LIT64( 0x8000000000000000 );
         }
         aSigExtra = 0;
         aSig <<= - shiftCount;
@@ -2663,7 +2663,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, shiftCount;
-    bits64 aSig;
+    uint64_t aSig;
     int64 z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
@@ -2683,7 +2683,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
                     return LIT64( 0x7FFFFFFFFFFFFFFF );
                 }
             }
-            return (sbits64) LIT64( 0x8000000000000000 );
+            return (int64_t) LIT64( 0x8000000000000000 );
         }
         z = aSig<<shiftCount;
     }
@@ -2693,7 +2693,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
             return 0;
         }
         z = aSig>>( - shiftCount );
-        if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+        if ( (uint64_t) ( aSig<<( shiftCount & 63 ) ) ) {
             STATUS(float_exception_flags) |= float_flag_inexact;
         }
     }
@@ -2713,8 +2713,8 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig;
-    bits32 zSig;
+    uint64_t aSig;
+    uint32_t zSig;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -2745,10 +2745,10 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
 | than the desired result exponent whenever `zSig' is a complete, normalized
 | significand.
 *----------------------------------------------------------------------------*/
-static float16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
+static float16 packFloat16(flag zSign, int16 zExp, uint16_t zSig)
 {
     return make_float16(
-        (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig);
+        (((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig);
 }
 
 /* Half precision floats come in two formats: standard IEEE and "ARM" format.
@@ -2758,7 +2758,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
 
     aSign = extractFloat16Sign(a);
     aExp = extractFloat16Exp(a);
@@ -2788,9 +2788,9 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
-    bits32 mask;
-    bits32 increment;
+    uint32_t aSig;
+    uint32_t mask;
+    uint32_t increment;
     int8 roundingMode;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
@@ -2891,7 +2891,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig;
+    uint64_t aSig;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat64Frac( a );
@@ -2926,7 +2926,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig, zSig0, zSig1;
+    uint64_t aSig, zSig0, zSig1;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat64Frac( a );
@@ -2959,9 +2959,9 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 lastBitMask, roundBitsMask;
+    uint64_t lastBitMask, roundBitsMask;
     int8 roundingMode;
-    bits64 z;
+    uint64_t z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aExp = extractFloat64Exp( a );
@@ -2972,7 +2972,7 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
         return a;
     }
     if ( aExp < 0x3FF ) {
-        if ( (bits64) ( float64_val(a)<<1 ) == 0 ) return a;
+        if ( (uint64_t) ( float64_val(a)<<1 ) == 0 ) return a;
         STATUS(float_exception_flags) |= float_flag_inexact;
         aSign = extractFloat64Sign( a );
         switch ( STATUS(float_rounding_mode) ) {
@@ -3032,7 +3032,7 @@ float64 float64_trunc_to_int( float64 a STATUS_PARAM)
 static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
 {
     int16 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig;
+    uint64_t aSig, bSig, zSig;
     int16 expDiff;
 
     aSig = extractFloat64Frac( a );
@@ -3086,7 +3086,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
     aSig |= LIT64( 0x2000000000000000 );
     zSig = ( aSig + bSig )<<1;
     --zExp;
-    if ( (sbits64) zSig < 0 ) {
+    if ( (int64_t) zSig < 0 ) {
         zSig = aSig + bSig;
         ++zExp;
     }
@@ -3106,7 +3106,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
 static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
 {
     int16 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig;
+    uint64_t aSig, bSig, zSig;
     int16 expDiff;
 
     aSig = extractFloat64Frac( a );
@@ -3226,7 +3226,7 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig0, zSig1;
+    uint64_t aSig, bSig, zSig0, zSig1;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
@@ -3269,7 +3269,7 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
     bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
     mul64To128( aSig, bSig, &zSig0, &zSig1 );
     zSig0 |= ( zSig1 != 0 );
-    if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
+    if ( 0 <= (int64_t) ( zSig0<<1 ) ) {
         zSig0 <<= 1;
         --zExp;
     }
@@ -3287,9 +3287,9 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int16 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig;
-    bits64 rem0, rem1;
-    bits64 term0, term1;
+    uint64_t aSig, bSig, zSig;
+    uint64_t rem0, rem1;
+    uint64_t term0, term1;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3339,7 +3339,7 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
     if ( ( zSig & 0x1FF ) <= 2 ) {
         mul64To128( bSig, zSig, &term0, &term1 );
         sub128( aSig, 0, term0, term1, &rem0, &rem1 );
-        while ( (sbits64) rem0 < 0 ) {
+        while ( (int64_t) rem0 < 0 ) {
             --zSig;
             add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
         }
@@ -3359,9 +3359,9 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, zSign;
     int16 aExp, bExp, expDiff;
-    bits64 aSig, bSig;
-    bits64 q, alternateASig;
-    sbits64 sigMean;
+    uint64_t aSig, bSig;
+    uint64_t q, alternateASig;
+    int64_t sigMean;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
@@ -3424,12 +3424,12 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
         alternateASig = aSig;
         ++q;
         aSig -= bSig;
-    } while ( 0 <= (sbits64) aSig );
+    } while ( 0 <= (int64_t) aSig );
     sigMean = aSig + alternateASig;
     if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
         aSig = alternateASig;
     }
-    zSign = ( (sbits64) aSig < 0 );
+    zSign = ( (int64_t) aSig < 0 );
     if ( zSign ) aSig = - aSig;
     return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig STATUS_VAR );
 
@@ -3445,8 +3445,8 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp, zExp;
-    bits64 aSig, zSig, doubleZSig;
-    bits64 rem0, rem1, term0, term1;
+    uint64_t aSig, zSig, doubleZSig;
+    uint64_t rem0, rem1, term0, term1;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -3476,7 +3476,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
         doubleZSig = zSig<<1;
         mul64To128( zSig, zSig, &term0, &term1 );
         sub128( aSig, 0, term0, term1, &rem0, &rem1 );
-        while ( (sbits64) rem0 < 0 ) {
+        while ( (int64_t) rem0 < 0 ) {
             --zSig;
             doubleZSig -= 2;
             add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
@@ -3496,7 +3496,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
 {
     flag aSign, zSign;
     int16 aExp;
-    bits64 aSig, aSig0, aSig1, zSig, i;
+    uint64_t aSig, aSig0, aSig1, zSig, i;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -3519,7 +3519,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
     aExp -= 0x3FF;
     aSig |= LIT64( 0x0010000000000000 );
     zSign = aExp < 0;
-    zSig = (bits64)aExp << 52;
+    zSig = (uint64_t)aExp << 52;
     for (i = 1LL << 51; i > 0; i >>= 1) {
         mul64To128( aSig, aSig, &aSig0, &aSig1 );
         aSig = ( aSig0 << 12 ) | ( aSig1 >> 52 );
@@ -3542,7 +3542,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
 
 int float64_eq( float64 a, float64 b STATUS_PARAM )
 {
-    bits64 av, bv;
+    uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3556,7 +3556,7 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
     }
     av = float64_val(a);
     bv = float64_val(b);
-    return ( av == bv ) || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -3570,7 +3570,7 @@ int float64_eq( float64 a, float64 b STATUS_PARAM )
 int float64_le( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits64 av, bv;
+    uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3584,7 +3584,7 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
     bSign = extractFloat64Sign( b );
     av = float64_val(a);
     bv = float64_val(b);
-    if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
     return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
@@ -3598,7 +3598,7 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
 int float64_lt( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits64 av, bv;
+    uint64_t av, bv;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
@@ -3612,7 +3612,7 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
     bSign = extractFloat64Sign( b );
     av = float64_val(a);
     bv = float64_val(b);
-    if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 );
+    if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
     return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
@@ -3626,7 +3626,7 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
 
 int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
 {
-    bits64 av, bv;
+    uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3638,7 +3638,7 @@ int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
     }
     av = float64_val(a);
     bv = float64_val(b);
-    return ( av == bv ) || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -3652,7 +3652,7 @@ int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
 int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits64 av, bv;
+    uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3668,7 +3668,7 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
     bSign = extractFloat64Sign( b );
     av = float64_val(a);
     bv = float64_val(b);
-    if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
     return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
@@ -3683,7 +3683,7 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
 int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
-    bits64 av, bv;
+    uint64_t av, bv;
     a = float64_squash_input_denormal(a STATUS_VAR);
     b = float64_squash_input_denormal(b STATUS_VAR);
 
@@ -3699,7 +3699,7 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
     bSign = extractFloat64Sign( b );
     av = float64_val(a);
     bv = float64_val(b);
-    if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 );
+    if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
     return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
@@ -3720,12 +3720,12 @@ int32 floatx80_to_int32( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig;
+    uint64_t aSig;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
-    if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+    if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0;
     shiftCount = 0x4037 - aExp;
     if ( shiftCount <= 0 ) shiftCount = 1;
     shift64RightJamming( aSig, shiftCount, &aSig );
@@ -3747,14 +3747,14 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig, savedASig;
+    uint64_t aSig, savedASig;
     int32 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( 0x401E < aExp ) {
-        if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+        if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0;
         goto invalid;
     }
     else if ( aExp < 0x3FFF ) {
@@ -3769,7 +3769,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+        return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig<<shiftCount ) != savedASig ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
@@ -3792,7 +3792,7 @@ int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig, aSigExtra;
+    uint64_t aSig, aSigExtra;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -3807,7 +3807,7 @@ int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
                ) {
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
-            return (sbits64) LIT64( 0x8000000000000000 );
+            return (int64_t) LIT64( 0x8000000000000000 );
         }
         aSigExtra = 0;
     }
@@ -3832,7 +3832,7 @@ int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig;
+    uint64_t aSig;
     int64 z;
 
     aSig = extractFloatx80Frac( a );
@@ -3847,14 +3847,14 @@ int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM )
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
         }
-        return (sbits64) LIT64( 0x8000000000000000 );
+        return (int64_t) LIT64( 0x8000000000000000 );
     }
     else if ( aExp < 0x3FFF ) {
         if ( aExp | aSig ) STATUS(float_exception_flags) |= float_flag_inexact;
         return 0;
     }
     z = aSig>>( - shiftCount );
-    if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+    if ( (uint64_t) ( aSig<<( shiftCount & 63 ) ) ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
     }
     if ( aSign ) z = - z;
@@ -3873,13 +3873,13 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig;
+    uint64_t aSig;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( aSig<<1 ) ) {
+        if ( (uint64_t) ( aSig<<1 ) ) {
             return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat32( aSign, 0xFF, 0 );
@@ -3901,13 +3901,13 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig, zSig;
+    uint64_t aSig, zSig;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( aSig<<1 ) ) {
+        if ( (uint64_t) ( aSig<<1 ) ) {
             return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
         }
         return packFloat64( aSign, 0x7FF, 0 );
@@ -3931,12 +3931,12 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig, zSig0, zSig1;
+    uint64_t aSig, zSig0, zSig1;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
-    if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
+    if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) {
         return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
     }
     shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
@@ -3957,27 +3957,27 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 lastBitMask, roundBitsMask;
+    uint64_t lastBitMask, roundBitsMask;
     int8 roundingMode;
     floatx80 z;
 
     aExp = extractFloatx80Exp( a );
     if ( 0x403E <= aExp ) {
-        if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
+        if ( ( aExp == 0x7FFF ) && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) {
             return propagateFloatx80NaN( a, a STATUS_VAR );
         }
         return a;
     }
     if ( aExp < 0x3FFF ) {
         if (    ( aExp == 0 )
-             && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+             && ( (uint64_t) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
             return a;
         }
         STATUS(float_exception_flags) |= float_flag_inexact;
         aSign = extractFloatx80Sign( a );
         switch ( STATUS(float_rounding_mode) ) {
          case float_round_nearest_even:
-            if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
+            if ( ( aExp == 0x3FFE ) && (uint64_t) ( extractFloatx80Frac( a )<<1 )
                ) {
                 return
                     packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
@@ -4030,7 +4030,7 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
 static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM)
 {
     int32 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig0, zSig1;
+    uint64_t aSig, bSig, zSig0, zSig1;
     int32 expDiff;
 
     aSig = extractFloatx80Frac( a );
@@ -4040,7 +4040,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     expDiff = aExp - bExp;
     if ( 0 < expDiff ) {
         if ( aExp == 0x7FFF ) {
-            if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+            if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
             return a;
         }
         if ( bExp == 0 ) --expDiff;
@@ -4049,7 +4049,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     }
     else if ( expDiff < 0 ) {
         if ( bExp == 0x7FFF ) {
-            if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+            if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
         }
         if ( aExp == 0 ) ++expDiff;
@@ -4058,7 +4058,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     }
     else {
         if ( aExp == 0x7FFF ) {
-            if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+            if ( (uint64_t) ( ( aSig | bSig )<<1 ) ) {
                 return propagateFloatx80NaN( a, b STATUS_VAR );
             }
             return a;
@@ -4073,7 +4073,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
         goto shiftRight1;
     }
     zSig0 = aSig + bSig;
-    if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
+    if ( (int64_t) zSig0 < 0 ) goto roundAndPack;
  shiftRight1:
     shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
     zSig0 |= LIT64( 0x8000000000000000 );
@@ -4096,7 +4096,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
 static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM )
 {
     int32 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig0, zSig1;
+    uint64_t aSig, bSig, zSig0, zSig1;
     int32 expDiff;
     floatx80 z;
 
@@ -4108,7 +4108,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     if ( 0 < expDiff ) goto aExpBigger;
     if ( expDiff < 0 ) goto bExpBigger;
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+        if ( (uint64_t) ( ( aSig | bSig )<<1 ) ) {
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
@@ -4126,7 +4126,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     return packFloatx80( STATUS(float_rounding_mode) == float_round_down, 0, 0 );
  bExpBigger:
     if ( bExp == 0x7FFF ) {
-        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( aExp == 0 ) ++expDiff;
@@ -4138,7 +4138,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM
     goto normalizeRoundAndPack;
  aExpBigger:
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         return a;
     }
     if ( bExp == 0 ) --expDiff;
@@ -4205,7 +4205,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig0, zSig1;
+    uint64_t aSig, bSig, zSig0, zSig1;
     floatx80 z;
 
     aSig = extractFloatx80Frac( a );
@@ -4216,15 +4216,15 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
     bSign = extractFloatx80Sign( b );
     zSign = aSign ^ bSign;
     if ( aExp == 0x7FFF ) {
-        if (    (bits64) ( aSig<<1 )
-             || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+        if (    (uint64_t) ( aSig<<1 )
+             || ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         if ( ( bExp | bSig ) == 0 ) goto invalid;
         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( bExp == 0x7FFF ) {
-        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
@@ -4244,7 +4244,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM )
     }
     zExp = aExp + bExp - 0x3FFE;
     mul64To128( aSig, bSig, &zSig0, &zSig1 );
-    if ( 0 < (sbits64) zSig0 ) {
+    if ( 0 < (int64_t) zSig0 ) {
         shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
         --zExp;
     }
@@ -4264,8 +4264,8 @@ floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
-    bits64 aSig, bSig, zSig0, zSig1;
-    bits64 rem0, rem1, rem2, term0, term1, term2;
+    uint64_t aSig, bSig, zSig0, zSig1;
+    uint64_t rem0, rem1, rem2, term0, term1, term2;
     floatx80 z;
 
     aSig = extractFloatx80Frac( a );
@@ -4276,15 +4276,15 @@ floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
     bSign = extractFloatx80Sign( b );
     zSign = aSign ^ bSign;
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         if ( bExp == 0x7FFF ) {
-            if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+            if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
             goto invalid;
         }
         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( bExp == 0x7FFF ) {
-        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         return packFloatx80( zSign, 0, 0 );
     }
     if ( bExp == 0 ) {
@@ -4314,15 +4314,15 @@ floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM )
     zSig0 = estimateDiv128To64( aSig, rem1, bSig );
     mul64To128( bSig, zSig0, &term0, &term1 );
     sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
-    while ( (sbits64) rem0 < 0 ) {
+    while ( (int64_t) rem0 < 0 ) {
         --zSig0;
         add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
     }
     zSig1 = estimateDiv128To64( rem1, 0, bSig );
-    if ( (bits64) ( zSig1<<1 ) <= 8 ) {
+    if ( (uint64_t) ( zSig1<<1 ) <= 8 ) {
         mul64To128( bSig, zSig1, &term1, &term2 );
         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
-        while ( (sbits64) rem1 < 0 ) {
+        while ( (int64_t) rem1 < 0 ) {
             --zSig1;
             add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
         }
@@ -4344,8 +4344,8 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, zSign;
     int32 aExp, bExp, expDiff;
-    bits64 aSig0, aSig1, bSig;
-    bits64 q, term0, term1, alternateASig0, alternateASig1;
+    uint64_t aSig0, aSig1, bSig;
+    uint64_t q, term0, term1, alternateASig0, alternateASig1;
     floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
@@ -4354,14 +4354,14 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
     bSig = extractFloatx80Frac( b );
     bExp = extractFloatx80Exp( b );
     if ( aExp == 0x7FFF ) {
-        if (    (bits64) ( aSig0<<1 )
-             || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+        if (    (uint64_t) ( aSig0<<1 )
+             || ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         goto invalid;
     }
     if ( bExp == 0x7FFF ) {
-        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
+        if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR );
         return a;
     }
     if ( bExp == 0 ) {
@@ -4375,7 +4375,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM )
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
     }
     if ( aExp == 0 ) {
-        if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
+        if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a;
         normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
     }
     bSig |= LIT64( 0x8000000000000000 );
@@ -4440,15 +4440,15 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, zExp;
-    bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0;
-    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
+    uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
     floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR );
+        if ( (uint64_t) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR );
         if ( ! aSign ) return a;
         goto invalid;
     }
@@ -4471,7 +4471,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
     doubleZSig0 = zSig0<<1;
     mul64To128( zSig0, zSig0, &term0, &term1 );
     sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
-    while ( (sbits64) rem0 < 0 ) {
+    while ( (int64_t) rem0 < 0 ) {
         --zSig0;
         doubleZSig0 -= 2;
         add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
@@ -4483,7 +4483,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
         mul64To128( zSig1, zSig1, &term2, &term3 );
         sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
-        while ( (sbits64) rem1 < 0 ) {
+        while ( (int64_t) rem1 < 0 ) {
             --zSig1;
             shortShift128Left( 0, zSig1, 1, &term2, &term3 );
             term3 |= 1;
@@ -4511,9 +4511,9 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
@@ -4525,7 +4525,7 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
            ( a.low == b.low )
         && (    ( a.high == b.high )
              || (    ( a.low == 0 )
-                  && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+                  && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
            );
 
 }
@@ -4542,9 +4542,9 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
     flag aSign, bSign;
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         float_raise( float_flag_invalid STATUS_VAR);
         return 0;
@@ -4554,7 +4554,7 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            || (    ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  == 0 );
     }
     return
@@ -4575,9 +4575,9 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
     flag aSign, bSign;
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         float_raise( float_flag_invalid STATUS_VAR);
         return 0;
@@ -4587,7 +4587,7 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            && (    ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  != 0 );
     }
     return
@@ -4607,9 +4607,9 @@ int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         float_raise( float_flag_invalid STATUS_VAR);
         return 0;
@@ -4618,7 +4618,7 @@ int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
            ( a.low == b.low )
         && (    ( a.high == b.high )
              || (    ( a.low == 0 )
-                  && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+                  && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
            );
 
 }
@@ -4635,9 +4635,9 @@ int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
     flag aSign, bSign;
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
@@ -4650,7 +4650,7 @@ int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            || (    ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  == 0 );
     }
     return
@@ -4671,9 +4671,9 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
     flag aSign, bSign;
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
-              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+              && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
         if (    floatx80_is_signaling_nan( a )
              || floatx80_is_signaling_nan( b ) ) {
@@ -4686,7 +4686,7 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            && (    ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  != 0 );
     }
     return
@@ -4713,7 +4713,7 @@ int32 float128_to_int32( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -4742,7 +4742,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig0, aSig1, savedASig;
+    uint64_t aSig0, aSig1, savedASig;
     int32 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -4767,7 +4767,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
     if ( ( z < 0 ) ^ aSign ) {
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+        return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
     }
     if ( ( aSig0<<shiftCount ) != savedASig ) {
         STATUS(float_exception_flags) |= float_flag_inexact;
@@ -4790,7 +4790,7 @@ int64 float128_to_int64( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -4808,7 +4808,7 @@ int64 float128_to_int64( float128 a STATUS_PARAM )
                ) {
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
-            return (sbits64) LIT64( 0x8000000000000000 );
+            return (int64_t) LIT64( 0x8000000000000000 );
         }
         shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
     }
@@ -4833,7 +4833,7 @@ int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, shiftCount;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
     int64 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -4855,10 +4855,10 @@ int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
                     return LIT64( 0x7FFFFFFFFFFFFFFF );
                 }
             }
-            return (sbits64) LIT64( 0x8000000000000000 );
+            return (int64_t) LIT64( 0x8000000000000000 );
         }
         z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
-        if ( (bits64) ( aSig1<<shiftCount ) ) {
+        if ( (uint64_t) ( aSig1<<shiftCount ) ) {
             STATUS(float_exception_flags) |= float_flag_inexact;
         }
     }
@@ -4871,7 +4871,7 @@ int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM )
         }
         z = aSig0>>( - shiftCount );
         if (    aSig1
-             || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
+             || ( shiftCount && (uint64_t) ( aSig0<<( shiftCount & 63 ) ) ) ) {
             STATUS(float_exception_flags) |= float_flag_inexact;
         }
     }
@@ -4891,8 +4891,8 @@ float32 float128_to_float32( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig0, aSig1;
-    bits32 zSig;
+    uint64_t aSig0, aSig1;
+    uint32_t zSig;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -4926,7 +4926,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -4961,7 +4961,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -4998,7 +4998,7 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 lastBitMask, roundBitsMask;
+    uint64_t lastBitMask, roundBitsMask;
     int8 roundingMode;
     float128 z;
 
@@ -5023,9 +5023,9 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
                 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
             }
             else {
-                if ( (sbits64) z.low < 0 ) {
+                if ( (int64_t) z.low < 0 ) {
                     ++z.high;
-                    if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1;
+                    if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1;
                 }
             }
         }
@@ -5039,7 +5039,7 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
     }
     else {
         if ( aExp < 0x3FFF ) {
-            if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
+            if ( ( ( (uint64_t) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
             STATUS(float_exception_flags) |= float_flag_inexact;
             aSign = extractFloat128Sign( a );
             switch ( STATUS(float_rounding_mode) ) {
@@ -5101,7 +5101,7 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
 static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
 {
     int32 aExp, bExp, zExp;
-    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+    uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
     int32 expDiff;
 
     aSig1 = extractFloat128Frac1( a );
@@ -5182,7 +5182,7 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM
 static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM)
 {
     int32 aExp, bExp, zExp;
-    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
+    uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
     int32 expDiff;
     float128 z;
 
@@ -5307,7 +5307,7 @@ float128 float128_mul( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
-    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
+    uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
     float128 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -5371,8 +5371,8 @@ float128 float128_div( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
-    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
-    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+    uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
     float128 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -5426,7 +5426,7 @@ float128 float128_div( float128 a, float128 b STATUS_PARAM )
     zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
     mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
     sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
-    while ( (sbits64) rem0 < 0 ) {
+    while ( (int64_t) rem0 < 0 ) {
         --zSig0;
         add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
     }
@@ -5434,7 +5434,7 @@ float128 float128_div( float128 a, float128 b STATUS_PARAM )
     if ( ( zSig1 & 0x3FFF ) <= 4 ) {
         mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
         sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
-        while ( (sbits64) rem1 < 0 ) {
+        while ( (int64_t) rem1 < 0 ) {
             --zSig1;
             add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
         }
@@ -5455,9 +5455,9 @@ float128 float128_rem( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, zSign;
     int32 aExp, bExp, expDiff;
-    bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
-    bits64 allZero, alternateASig0, alternateASig1, sigMean1;
-    sbits64 sigMean0;
+    uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
+    uint64_t allZero, alternateASig0, alternateASig1, sigMean1;
+    int64_t sigMean0;
     float128 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -5539,15 +5539,15 @@ float128 float128_rem( float128 a, float128 b STATUS_PARAM )
         alternateASig1 = aSig1;
         ++q;
         sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
-    } while ( 0 <= (sbits64) aSig0 );
+    } while ( 0 <= (int64_t) aSig0 );
     add128(
-        aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 );
+        aSig0, aSig1, alternateASig0, alternateASig1, (uint64_t *)&sigMean0, &sigMean1 );
     if (    ( sigMean0 < 0 )
          || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
         aSig0 = alternateASig0;
         aSig1 = alternateASig1;
     }
-    zSign = ( (sbits64) aSig0 < 0 );
+    zSign = ( (int64_t) aSig0 < 0 );
     if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
     return
         normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 STATUS_VAR );
@@ -5564,8 +5564,8 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
 {
     flag aSign;
     int32 aExp, zExp;
-    bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
-    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
+    uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
     float128 z;
 
     aSig1 = extractFloat128Frac1( a );
@@ -5597,7 +5597,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
     doubleZSig0 = zSig0<<1;
     mul64To128( zSig0, zSig0, &term0, &term1 );
     sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
-    while ( (sbits64) rem0 < 0 ) {
+    while ( (int64_t) rem0 < 0 ) {
         --zSig0;
         doubleZSig0 -= 2;
         add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
@@ -5609,7 +5609,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
         sub128( rem1, 0, term1, term2, &rem1, &rem2 );
         mul64To128( zSig1, zSig1, &term2, &term3 );
         sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
-        while ( (sbits64) rem1 < 0 ) {
+        while ( (int64_t) rem1 < 0 ) {
             --zSig1;
             shortShift128Left( 0, zSig1, 1, &term2, &term3 );
             term3 |= 1;
@@ -5647,7 +5647,7 @@ int float128_eq( float128 a, float128 b STATUS_PARAM )
            ( a.low == b.low )
         && (    ( a.high == b.high )
              || (    ( a.low == 0 )
-                  && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+                  && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
            );
 
 }
@@ -5676,7 +5676,7 @@ int float128_le( float128 a, float128 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            || (    ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  == 0 );
     }
     return
@@ -5708,7 +5708,7 @@ int float128_lt( float128 a, float128 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            && (    ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  != 0 );
     }
     return
@@ -5739,7 +5739,7 @@ int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
            ( a.low == b.low )
         && (    ( a.high == b.high )
              || (    ( a.low == 0 )
-                  && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+                  && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
            );
 
 }
@@ -5771,7 +5771,7 @@ int float128_le_quiet( float128 a, float128 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            || (    ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  == 0 );
     }
     return
@@ -5807,7 +5807,7 @@ int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
     if ( aSign != bSign ) {
         return
                aSign
-            && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+            && (    ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
                  != 0 );
     }
     return
@@ -5965,7 +5965,7 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
                                       int is_quiet STATUS_PARAM )            \
 {                                                                            \
     flag aSign, bSign;                                                       \
-    bits ## s av, bv;                                                        \
+    uint ## s ## _t av, bv;                                                  \
     a = float ## s ## _squash_input_denormal(a STATUS_VAR);                  \
     b = float ## s ## _squash_input_denormal(b STATUS_VAR);                  \
                                                                              \
@@ -5985,7 +5985,7 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
     av = float ## s ## _val(a);                                              \
     bv = float ## s ## _val(b);                                              \
     if ( aSign != bSign ) {                                                  \
-        if ( (bits ## s) ( ( av | bv )<<1 ) == 0 ) {                         \
+        if ( (uint ## s ## _t) ( ( av | bv )<<1 ) == 0 ) {                   \
             /* zero case */                                                  \
             return float_relation_equal;                                     \
         } else {                                                             \
@@ -6062,7 +6062,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits32 aSig;
+    uint32_t aSig;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat32Frac( a );
@@ -6086,7 +6086,7 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig;
+    uint64_t aSig;
 
     a = float64_squash_input_denormal(a STATUS_VAR);
     aSig = extractFloat64Frac( a );
@@ -6111,7 +6111,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
 {
     flag aSign;
     int16 aExp;
-    bits64 aSig;
+    uint64_t aSig;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -6134,7 +6134,7 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
 {
     flag aSign;
     int32 aExp;
-    bits64 aSig0, aSig1;
+    uint64_t aSig0, aSig1;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 29492bc..5d05fa5 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -65,21 +65,6 @@ typedef signed int int32;
 typedef uint64_t uint64;
 typedef int64_t int64;
 
-/*----------------------------------------------------------------------------
-| Each of the following `typedef's defines a type that holds integers
-| of _exactly_ the number of bits specified.  For instance, for most
-| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
-| `unsigned short int' and `signed short int' (or `short int'), respectively.
-*----------------------------------------------------------------------------*/
-typedef uint8_t bits8;
-typedef int8_t sbits8;
-typedef uint16_t bits16;
-typedef int16_t sbits16;
-typedef uint32_t bits32;
-typedef int32_t sbits32;
-typedef uint64_t bits64;
-typedef int64_t sbits64;
-
 #define LIT64( a ) a##LL
 #define INLINE static inline
 
commit 87b8cc3cf31d3e39c7b8f2d72332a2792a4e33b1
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon Mar 7 01:34:05 2011 +0100

    softfloat: Resolve type mismatches between declaration and implementation
    
    The original SoftFloat 2.0b library avoided the use of custom integer types
    in its public headers. This requires the definitions of int{8,16,32,64} to
    match the assumptions in the declarations. This breaks on BeOS R5 and Haiku/x86,
    where int32 is defined in {be,os}/support/SupportDefs.h in terms of a long
    rather than an int. Spotted by Michael Lotz.
    
    Since QEMU already breaks this distinction by defining those types just above,
    do use them for consistency and to allow #ifndef'ing them out as done for
    [u]int16 on AIX.
    
    Cc: Michael Lotz <mmlr at mlotz.ch>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 9e10727..29492bc 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -255,25 +255,25 @@ void float_raise( int8 flags STATUS_PARAM);
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE integer-to-floating-point conversion routines.
 *----------------------------------------------------------------------------*/
-float32 int32_to_float32( int STATUS_PARAM );
-float64 int32_to_float64( int STATUS_PARAM );
+float32 int32_to_float32( int32 STATUS_PARAM );
+float64 int32_to_float64( int32 STATUS_PARAM );
 float32 uint32_to_float32( unsigned int STATUS_PARAM );
 float64 uint32_to_float64( unsigned int STATUS_PARAM );
 #ifdef FLOATX80
-floatx80 int32_to_floatx80( int STATUS_PARAM );
+floatx80 int32_to_floatx80( int32 STATUS_PARAM );
 #endif
 #ifdef FLOAT128
-float128 int32_to_float128( int STATUS_PARAM );
+float128 int32_to_float128( int32 STATUS_PARAM );
 #endif
-float32 int64_to_float32( int64_t STATUS_PARAM );
-float32 uint64_to_float32( uint64_t STATUS_PARAM );
-float64 int64_to_float64( int64_t STATUS_PARAM );
-float64 uint64_to_float64( uint64_t STATUS_PARAM );
+float32 int64_to_float32( int64 STATUS_PARAM );
+float32 uint64_to_float32( uint64 STATUS_PARAM );
+float64 int64_to_float64( int64 STATUS_PARAM );
+float64 uint64_to_float64( uint64 STATUS_PARAM );
 #ifdef FLOATX80
-floatx80 int64_to_floatx80( int64_t STATUS_PARAM );
+floatx80 int64_to_floatx80( int64 STATUS_PARAM );
 #endif
 #ifdef FLOAT128
-float128 int64_to_float128( int64_t STATUS_PARAM );
+float128 int64_to_float128( int64 STATUS_PARAM );
 #endif
 
 /*----------------------------------------------------------------------------
@@ -303,14 +303,14 @@ float16 float16_maybe_silence_nan( float16 );
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
 *----------------------------------------------------------------------------*/
-int float32_to_int16_round_to_zero( float32 STATUS_PARAM );
+int16 float32_to_int16_round_to_zero( float32 STATUS_PARAM );
 unsigned int float32_to_uint16_round_to_zero( float32 STATUS_PARAM );
-int float32_to_int32( float32 STATUS_PARAM );
-int float32_to_int32_round_to_zero( float32 STATUS_PARAM );
-unsigned int float32_to_uint32( float32 STATUS_PARAM );
-unsigned int float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
-int64_t float32_to_int64( float32 STATUS_PARAM );
-int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM );
+int32 float32_to_int32( float32 STATUS_PARAM );
+int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM );
+uint32 float32_to_uint32( float32 STATUS_PARAM );
+uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
+int64 float32_to_int64( float32 STATUS_PARAM );
+int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
 float64 float32_to_float64( float32 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float32_to_floatx80( float32 STATUS_PARAM );
@@ -413,16 +413,16 @@ INLINE float32 float32_set_sign(float32 a, int sign)
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
-int float64_to_int16_round_to_zero( float64 STATUS_PARAM );
+int16 float64_to_int16_round_to_zero( float64 STATUS_PARAM );
 unsigned int float64_to_uint16_round_to_zero( float64 STATUS_PARAM );
-int float64_to_int32( float64 STATUS_PARAM );
-int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
-unsigned int float64_to_uint32( float64 STATUS_PARAM );
-unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
-int64_t float64_to_int64( float64 STATUS_PARAM );
-int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
-uint64_t float64_to_uint64 (float64 a STATUS_PARAM);
-uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
+int32 float64_to_int32( float64 STATUS_PARAM );
+int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM );
+uint32 float64_to_uint32( float64 STATUS_PARAM );
+uint32 float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
+int64 float64_to_int64( float64 STATUS_PARAM );
+int64 float64_to_int64_round_to_zero( float64 STATUS_PARAM );
+uint64 float64_to_uint64 (float64 a STATUS_PARAM);
+uint64 float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
 float32 float64_to_float32( float64 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 STATUS_PARAM );
@@ -522,10 +522,10 @@ INLINE float64 float64_set_sign(float64 a, int sign)
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
 *----------------------------------------------------------------------------*/
-int floatx80_to_int32( floatx80 STATUS_PARAM );
-int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
-int64_t floatx80_to_int64( floatx80 STATUS_PARAM );
-int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
+int32 floatx80_to_int32( floatx80 STATUS_PARAM );
+int32 floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
+int64 floatx80_to_int64( floatx80 STATUS_PARAM );
+int64 floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
 float32 floatx80_to_float32( floatx80 STATUS_PARAM );
 float64 floatx80_to_float64( floatx80 STATUS_PARAM );
 #ifdef FLOAT128
@@ -605,10 +605,10 @@ INLINE int floatx80_is_any_nan(floatx80 a)
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
 *----------------------------------------------------------------------------*/
-int float128_to_int32( float128 STATUS_PARAM );
-int float128_to_int32_round_to_zero( float128 STATUS_PARAM );
-int64_t float128_to_int64( float128 STATUS_PARAM );
-int64_t float128_to_int64_round_to_zero( float128 STATUS_PARAM );
+int32 float128_to_int32( float128 STATUS_PARAM );
+int32 float128_to_int32_round_to_zero( float128 STATUS_PARAM );
+int64 float128_to_int64( float128 STATUS_PARAM );
+int64 float128_to_int64_round_to_zero( float128 STATUS_PARAM );
 float32 float128_to_float32( float128 STATUS_PARAM );
 float64 float128_to_float64( float128 STATUS_PARAM );
 #ifdef FLOATX80
commit 8d725fac63c31562cdc25e332634a6583ca7b9b5
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Mon Mar 7 01:34:04 2011 +0100

    softfloat: Prepend QEMU-style header with derivation notice
    
    The SoftFloat license requires "prominent notice that the work
    is derivative". Having added features like improved 16-bit support
    for arm already, add such a notice to the sources.
    
    softfloat-native.[ch] are not under the SoftFloat license
    and thus are not changed.
    
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index 7838228..54c0bad 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -1,3 +1,8 @@
+/*
+ * QEMU float support macros
+ *
+ * Derived from SoftFloat.
+ */
 
 /*============================================================================
 
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index adc5ada..4add93c 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -1,3 +1,8 @@
+/*
+ * QEMU float support
+ *
+ * Derived from SoftFloat.
+ */
 
 /*============================================================================
 
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 30b07e9..e800daa 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1,3 +1,8 @@
+/*
+ * QEMU float support
+ *
+ * Derived from SoftFloat.
+ */
 
 /*============================================================================
 
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index fd61dc4..9e10727 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -1,3 +1,9 @@
+/*
+ * QEMU float support
+ *
+ * Derived from SoftFloat.
+ */
+
 /*============================================================================
 
 This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
commit 735e77ecb14355df35c9dbb727f3bc76d730b651
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 7 20:04:07 2011 +0000

    e1000: Fix multi-descriptor packet checksum offload
    
    The PCI/PCI-X Family of Gigabit Ethernet Controllers Software
    Developer’s Manual states the following about the POPTS field:
    
      Provides a number of options which control the handling of this
      packet.  This field is ignored except on the first data descriptor of
      a packet.
    
    The current implementation always loads the field and its checksum
    offload flags.  This patch uses only the first descriptor's POPTS field
    in order to comply with the specification.
    
    When Solaris sends multi-descriptor packets it fills in POPTS for the
    first descriptor only.  Therefore this patch is necessary in order to
    perform checksum offload correctly for multi-descriptor packets.
    
    Reported-by: Daniel Pecka <dpecka at techniservit.cz>
    Reported-by: Gabriele A. Trombetti <gabriele.trombetti at itb.cnr.it>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/e1000.c b/hw/e1000.c
index 0a4574c..2a4d5c7 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -446,7 +446,9 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
         return;
     } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
         // data descriptor
-        tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
+        if (tp->size == 0) {
+            tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
+        }
         tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
     } else {
         // legacy descriptor
commit aa315f95b7c3c5b032cbc6c78f434a871002f558
Merge: 3246572... 6d5ad9b...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Mar 21 21:28:38 2011 +0100

    Merge branch 'for-anthony' of git://github.com/bonzini/qemu
    
    * 'for-anthony' of git://github.com/bonzini/qemu:
      remove qemu_get_clock
      add a generic scaling mechanism for timers
      change all other clock references to use nanosecond resolution accessors
      change all rt_clock references to use millisecond resolution accessors
      add more helper functions with explicit milli/nanosecond resolution

commit 32465727627711ff3e1cde6777a014413c3cb9ee
Merge: cc4e874... 03feae7...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Mar 21 21:28:19 2011 +0100

    Merge branch 'for-anthony' of git://repo.or.cz/qemu/kevin
    
    * 'for-anthony' of git://repo.or.cz/qemu/kevin:
      Add qcow2 documentation
      hw/xen_disk: aio_inflight not released in handling ioreq when nr_segments==0
      Improve error handling in do_snapshot_blkdev()
      Fix ATA SMART and CHECK POWER MODE
      Don't allow multiwrites against a block device without underlying medium
      tools: Use real async.c instead of stubs
      Add error message for loading snapshot without VM state
      block/qcow: Don't ignore immediate read/write and other failures
      block/vdi: Don't ignore immediate read/write failures

commit cc4e8741ccdaa905017f3c7c59e14c685a239c2d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Mar 7 07:17:49 2011 +0100

    rbd: don't link with -lcrypto
    
    rbd support tries to both link with -lrados and -lcrypto. While the
    first one is of course necessary, the second is not necessary (only
    librados ifself needs to link with libcrypto).
    
    This fixes a licensing issue: qemu as a whole is GPL v2, and thus can't
    be linked with OpenSSL without an exception in the license, which seems
    difficult to get given the number of persons involved.
    
    Cc: Christian Brunner <chb at muc.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index a166de0..b523a6e 100755
--- a/configure
+++ b/configure
@@ -1802,7 +1802,7 @@ if test "$rbd" != "no" ; then
 #include <rados/librados.h>
 int main(void) { rados_initialize(0, NULL); return 0; }
 EOF
-  rbd_libs="-lrados -lcrypto"
+  rbd_libs="-lrados"
   if compile_prog "" "$rbd_libs" ; then
     librados_too_old=no
     cat > $TMPC <<EOF
commit 34933c8c9485992f2a7d318bb23f313343f3ac10
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 7 11:10:31 2011 +0000

    hw/arm_sysctl.c: Add the Versatile Express system registers
    
    Add support for the Versatile Express SYS_CFG registers, which provide
    a generic means of reading or writing configuration information from
    various parts of the board. We only implement shutdown and reset.
    
    Also make the RESETCTL register RAZ/WI on Versatile Express rather
    than reset the board. Other system registers are generally the same
    as Versatile and Realview.
    
    This includes a VMState version number bump for arm_sysctl,
    since we have new register state to preserve. It also adds
    sys_mci to the VMState while we're bumping the version number
    (an accidental omission from commit b50ff6f5).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 799b007..b1110b4 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -27,11 +27,14 @@ typedef struct {
     uint32_t resetlevel;
     uint32_t proc_id;
     uint32_t sys_mci;
+    uint32_t sys_cfgdata;
+    uint32_t sys_cfgctrl;
+    uint32_t sys_cfgstat;
 } arm_sysctl_state;
 
 static const VMStateDescription vmstate_arm_sysctl = {
     .name = "realview_sysctl",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(leds, arm_sysctl_state),
@@ -41,6 +44,10 @@ static const VMStateDescription vmstate_arm_sysctl = {
         VMSTATE_UINT32(flags, arm_sysctl_state),
         VMSTATE_UINT32(nvflags, arm_sysctl_state),
         VMSTATE_UINT32(resetlevel, arm_sysctl_state),
+        VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2),
+        VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
+        VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
+        VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -53,6 +60,7 @@ static const VMStateDescription vmstate_arm_sysctl = {
 #define BOARD_ID_EB 0x140
 #define BOARD_ID_PBA8 0x178
 #define BOARD_ID_PBX 0x182
+#define BOARD_ID_VEXPRESS 0x190
 
 static int board_id(arm_sysctl_state *s)
 {
@@ -104,6 +112,10 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
     case 0x38: /* NVFLAGS */
         return s->nvflags;
     case 0x40: /* RESETCTL */
+        if (board_id(s) == BOARD_ID_VEXPRESS) {
+            /* reserved: RAZ/WI */
+            return 0;
+        }
         return s->resetlevel;
     case 0x44: /* PCICTL */
         return 1;
@@ -142,7 +154,23 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
     case 0xcc: /* SYS_TEST_OSC3 */
     case 0xd0: /* SYS_TEST_OSC4 */
         return 0;
+    case 0xa0: /* SYS_CFGDATA */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        return s->sys_cfgdata;
+    case 0xa4: /* SYS_CFGCTRL */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        return s->sys_cfgctrl;
+    case 0xa8: /* SYS_CFGSTAT */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        return s->sys_cfgstat;
     default:
+    bad_reg:
         printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
         return 0;
     }
@@ -190,6 +218,10 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
         s->nvflags &= ~val;
         break;
     case 0x40: /* RESETCTL */
+        if (board_id(s) == BOARD_ID_VEXPRESS) {
+            /* reserved: RAZ/WI */
+            break;
+        }
         if (s->lockval == LOCK_VALUE) {
             s->resetlevel = val;
             if (val & 0x100)
@@ -216,7 +248,37 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
     case 0x98: /* OSCRESET3 */
     case 0x9c: /* OSCRESET4 */
         break;
+    case 0xa0: /* SYS_CFGDATA */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        s->sys_cfgdata = val;
+        return;
+    case 0xa4: /* SYS_CFGCTRL */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        s->sys_cfgctrl = val & ~(3 << 18);
+        s->sys_cfgstat = 1;            /* complete */
+        switch (s->sys_cfgctrl) {
+        case 0xc0800000:            /* SYS_CFG_SHUTDOWN to motherboard */
+            qemu_system_shutdown_request();
+            break;
+        case 0xc0900000:            /* SYS_CFG_REBOOT to motherboard */
+            qemu_system_reset_request();
+            break;
+        default:
+            s->sys_cfgstat |= 2;        /* error */
+        }
+        return;
+    case 0xa8: /* SYS_CFGSTAT */
+        if (board_id(s) != BOARD_ID_VEXPRESS) {
+            goto bad_reg;
+        }
+        s->sys_cfgstat = val & 3;
+        return;
     default:
+    bad_reg:
         printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
         return;
     }
commit 2d6c1ef40f3678ab47a4d14fb5dadaa486bfcda6
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Feb 10 12:55:20 2011 +0530

    char: Prevent multiple devices opening same chardev
    
    Prevent:
    
    -chardev socket,path=/tmp/foo,server,nowait,id=c0 \
    -device virtserialport,chardev=c0,id=vs0 \
    -device virtserialport,chardev=c0,id=vs1
    
    Reported-by: Mike Cao <bcao at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index a45b61e..1088a26 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -351,8 +351,13 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str)
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     *ptr = qemu_chr_find(str);
-    if (*ptr == NULL)
+    if (*ptr == NULL) {
         return -ENOENT;
+    }
+    if ((*ptr)->assigned) {
+        return -EEXIST;
+    }
+    (*ptr)->assigned = 1;
     return 0;
 }
 
diff --git a/qemu-char.c b/qemu-char.c
index cad35d7..c4557c3 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -197,6 +197,10 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque)
 {
+    if (!opaque) {
+        /* chr driver being released. */
+        s->assigned = 0;
+    }
     s->chr_can_read = fd_can_read;
     s->chr_read = fd_read;
     s->chr_event = fd_event;
diff --git a/qemu-char.h b/qemu-char.h
index 56d9954..fb96eef 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -70,6 +70,7 @@ struct CharDriverState {
     char *label;
     char *filename;
     int opened;
+    int assigned; /* chardev assigned to a device */
     QTAILQ_ENTRY(CharDriverState) next;
 };
 
commit f9a90f189c780e066039f2de3906c73c48071bb7
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Mar 15 14:13:09 2011 +0530

    virtio-console: Keep chardev open for other users after hot-unplug
    
    After a hot-unplug operation, the previous behaviour was to close the
    chardev.  That meant the chardev couldn't be re-used.  Also, since
    chardev hot-plug isn't possible so far, this means virtio-console
    hot-plug isn't feasible as well.
    
    With this change, the chardev is kept around.  A new virtio-console
    channel can then be hot-plugged with the same chardev and things will
    continue to work.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index be59558..6b5237b 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -82,7 +82,11 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     if (vcon->chr) {
-        qemu_chr_close(vcon->chr);
+	/*
+	 * Instead of closing the chardev, free it so it can be used
+	 * for other purposes.
+	 */
+	qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
     }
 
     return 0;
commit fee063c07f20b442ef4bedef834ab0a3bf55b562
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Mar 3 13:29:45 2011 +0530

    virtio-serial: Don't clear ->have_data() pointer after unplug
    
    After a port unplug operation, the port->info->have_data() pointer was
    set to NULL.  The problem is, the ->info struct is shared by all ports,
    effectively disabling writes to other ports.
    
    Reported-by: juzhang <juzhang at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 4440784..be59558 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -82,7 +82,6 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     if (vcon->chr) {
-        port->info->have_data = NULL;
         qemu_chr_close(vcon->chr);
     }
 
commit e9b382b0170ee045295f2ff0ce1009a01a11eb1f
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Mar 3 13:28:55 2011 +0530

    virtio-serial-bus: Simplify handle_output() function
    
    There's no code change, just re-arrangement to simplify the function
    after recent modifications.
    
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index c6feb43..a82fbe9 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -442,25 +442,19 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSerial *vser;
     VirtIOSerialPort *port;
-    bool discard;
 
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
     port = find_port_by_vq(vser, vq);
 
-    discard = false;
     if (!port || !port->host_connected || !port->info->have_data) {
-        discard = true;
-    }
-
-    if (discard) {
         discard_vq_data(vq, vdev);
         return;
     }
-    if (port->throttled) {
+
+    if (!port->throttled) {
+        do_flush_queued_data(port, vq, vdev);
         return;
     }
-
-    do_flush_queued_data(port, vq, vdev);
 }
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
commit 32059220d02cf8e779bbaf9966d12501c32e2076
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Feb 17 12:31:10 2011 +0530

    virtio-serial: Enable ioeventfd
    
    Enable ioeventfd for virtio-serial devices by default.  Commit
    25db9ebe15125deb32958c6df74996f745edf1f9 lists the benefits of using
    ioeventfd.
    
    Copying a file from guest to host over a virtio-serial channel didn't
    show much difference in time or io_exit rate.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 952b5d2..ef65590 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -789,6 +789,7 @@ static int virtio_serial_exit_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 
+    virtio_pci_stop_ioeventfd(proxy);
     virtio_serial_exit(proxy->vdev);
     return virtio_exit_pci(pci_dev);
 }
@@ -898,6 +899,8 @@ static PCIDeviceInfo virtio_info[] = {
         .init      = virtio_serial_init_pci,
         .exit      = virtio_serial_exit_pci,
         .qdev.props = (Property[]) {
+            DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                            VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
                                DEV_NVECTORS_UNSPECIFIED),
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
commit 0b8b716d6c43b5a1d4e0293df1c77af4fff21bab
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Feb 3 13:05:07 2011 +0530

    virtio-serial: Disallow generic ports at id 0
    
    Port 0 is reserved for virtconsole devices for backward compatibility
    with the old -virtioconsole (from qemu 0.12) device type.
    
    libvirt prior to commit 8e28c5d40200b4c5d483bd585d237b9d870372e5 used
    port 0 for generic ports.  libvirt will no longer do that, but disallow
    instantiating generic ports at id 0 from qemu as well.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index c235b27..4440784 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -11,6 +11,7 @@
  */
 
 #include "qemu-char.h"
+#include "qemu-error.h"
 #include "virtio-serial.h"
 
 typedef struct VirtConsole {
@@ -113,6 +114,14 @@ static int virtserialport_initfn(VirtIOSerialPort *port)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
+    if (port->id == 0) {
+        /*
+         * Disallow a generic port at id 0, that's reserved for
+         * console ports.
+         */
+        error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
+        return -1;
+    }
     return generic_port_init(vcon, port);
 }
 
commit 6b331efb733a0f913ddc0b7762a1307dec304061
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Feb 3 11:22:32 2011 +0530

    virtio-serial: Use a struct to pass config information from proxy
    
    Instead of using a single variable to pass to the virtio_serial_init
    function, use a struct so that expanding the number of variables to be
    passed on later is easier.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 3911b09..952b5d2 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -18,6 +18,7 @@
 #include "virtio.h"
 #include "virtio-blk.h"
 #include "virtio-net.h"
+#include "virtio-serial.h"
 #include "pci.h"
 #include "qemu-error.h"
 #include "msix.h"
@@ -109,8 +110,7 @@ typedef struct {
 #ifdef CONFIG_LINUX
     V9fsConf fsconf;
 #endif
-    /* Max. number of ports we can have for a the virtio-serial device */
-    uint32_t max_virtserial_ports;
+    virtio_serial_conf serial;
     virtio_net_conf net;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
@@ -770,12 +770,12 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
         proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
         proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
 
-    vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports);
+    vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
     if (!vdev) {
         return -1;
     }
     vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
-                                        ? proxy->max_virtserial_ports + 1
+                                        ? proxy->serial.max_virtserial_ports + 1
                                         : proxy->nvectors;
     virtio_init_pci(proxy, vdev,
                     PCI_VENDOR_ID_REDHAT_QUMRANET,
@@ -902,8 +902,8 @@ static PCIDeviceInfo virtio_info[] = {
                                DEV_NVECTORS_UNSPECIFIED),
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
             DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
-                               31),
+            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy,
+                               serial.max_virtserial_ports, 31),
             DEFINE_PROP_END_OF_LIST(),
         },
         .qdev.reset = virtio_pci_reset,
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 8446bc2..c6feb43 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -811,19 +811,19 @@ void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info)
     qdev_register(&info->qdev);
 }
 
-VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
+VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
 {
     VirtIOSerial *vser;
     VirtIODevice *vdev;
     uint32_t i, max_supported_ports;
 
-    if (!max_nr_ports)
+    if (!conf->max_virtserial_ports)
         return NULL;
 
     /* Each port takes 2 queues, and one pair is for the control queue */
     max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
 
-    if (max_nr_ports > max_supported_ports) {
+    if (conf->max_virtserial_ports > max_supported_ports) {
         error_report("maximum ports supported: %u", max_supported_ports);
         return NULL;
     }
@@ -839,9 +839,9 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
     vser->bus->vser = vser;
     QTAILQ_INIT(&vser->ports);
 
-    vser->bus->max_nr_ports = max_nr_ports;
-    vser->ivqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *));
-    vser->ovqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *));
+    vser->bus->max_nr_ports = conf->max_virtserial_ports;
+    vser->ivqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
+    vser->ovqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
 
     /* Add a queue for host to guest transfers for port 0 (backward compat) */
     vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
@@ -866,8 +866,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
         vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
     }
 
-    vser->config.max_nr_ports = max_nr_ports;
-    vser->ports_map = qemu_mallocz(((max_nr_ports + 31) / 32)
+    vser->config.max_nr_ports = conf->max_virtserial_ports;
+    vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32)
         * sizeof(vser->ports_map[0]));
     /*
      * Reserve location 0 for a console port for backward compat
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 8cb9fbe..5eb948e 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -45,6 +45,11 @@ struct virtio_console_control {
     uint16_t value;		/* Extra information for the key */
 };
 
+struct virtio_serial_conf {
+    /* Max. number of ports we can have for a virtio-serial device */
+    uint32_t max_virtserial_ports;
+};
+
 /* Some events for the internal messages (control packets) */
 #define VIRTIO_CONSOLE_DEVICE_READY	0
 #define VIRTIO_CONSOLE_PORT_ADD		1
diff --git a/hw/virtio.h b/hw/virtio.h
index 31d16e1..d0920a8 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -195,7 +195,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
 struct virtio_net_conf;
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               struct virtio_net_conf *net);
-VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
+typedef struct virtio_serial_conf virtio_serial_conf;
+VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
 #ifdef CONFIG_LINUX
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
commit 6d5ad9bf9318b1555d5567cd7e1760a51a55ebf8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 11 18:27:26 2011 +0100

    remove qemu_get_clock
    
    These patches are already not doing a great service to out-of-tree
    modifications to QEMU.  However, at least we can warn them by getting
    rid of the old confusing functions, or otherwise causing compilation
    errors.  This patch removes qemu_get_clock; the previous one changed
    qemu_new_timer's signature.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index ec8b446..50f1943 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -506,23 +506,6 @@ static void qemu_run_timers(QEMUClock *clock)
     }
 }
 
-int64_t qemu_get_clock(QEMUClock *clock)
-{
-    switch(clock->type) {
-    case QEMU_CLOCK_REALTIME:
-        return get_clock() / 1000000;
-    default:
-    case QEMU_CLOCK_VIRTUAL:
-        if (use_icount) {
-            return cpu_get_icount();
-        } else {
-            return cpu_get_clock();
-        }
-    case QEMU_CLOCK_HOST:
-        return get_clock_realtime();
-    }
-}
-
 int64_t qemu_get_clock_ns(QEMUClock *clock)
 {
     switch(clock->type) {
diff --git a/qemu-timer.h b/qemu-timer.h
index 0ea77fb..75d5675 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -37,7 +37,6 @@ extern QEMUClock *vm_clock;
    the virtual clock. */
 extern QEMUClock *host_clock;
 
-int64_t qemu_get_clock(QEMUClock *clock);
 int64_t qemu_get_clock_ns(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
 
commit 4a998740b22aa673ea475060c787da7c545588cf
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 11 16:33:58 2011 +0100

    add a generic scaling mechanism for timers
    
    This enables rt_clock timers to use nanosecond resolution, just by
    using the _ns functions; there is really no reason to forbid that.
    
    Migrated timers are all using vm_clock (of course; but I checked that
    anyway) so the timers in the savevm files are already in nanosecond
    resolution.  So this patch makes no change to the migration format.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index bc818ae..ec8b446 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -153,12 +153,12 @@ void cpu_disable_ticks(void)
 struct QEMUClock {
     int type;
     int enabled;
-    /* XXX: add frequency */
 };
 
 struct QEMUTimer {
     QEMUClock *clock;
-    int64_t expire_time;
+    int64_t expire_time;	/* in nanoseconds */
+    int scale;
     QEMUTimerCB *cb;
     void *opaque;
     struct QEMUTimer *next;
@@ -386,7 +386,8 @@ void qemu_clock_enable(QEMUClock *clock, int enabled)
     clock->enabled = enabled;
 }
 
-QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
+QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
+                          QEMUTimerCB *cb, void *opaque)
 {
     QEMUTimer *ts;
 
@@ -394,6 +395,7 @@ QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
     ts->clock = clock;
     ts->cb = cb;
     ts->opaque = opaque;
+    ts->scale = scale;
     return ts;
 }
 
@@ -424,7 +426,7 @@ void qemu_del_timer(QEMUTimer *ts)
 
 /* modify the current timer so that it will be fired when current_time
    >= expire_time. The corresponding callback will be called. */
-void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
+static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
 {
     QEMUTimer **pt, *t;
 
@@ -457,6 +459,13 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
     }
 }
 
+/* modify the current timer so that it will be fired when current_time
+   >= expire_time. The corresponding callback will be called. */
+void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
+{
+    qemu_mod_timer_ns(ts, expire_time * ts->scale);
+}
+
 int qemu_timer_pending(QEMUTimer *ts)
 {
     QEMUTimer *t;
@@ -471,7 +480,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
 {
     if (!timer_head)
         return 0;
-    return (timer_head->expire_time <= current_time);
+    return (timer_head->expire_time <= current_time * timer_head->scale);
 }
 
 static void qemu_run_timers(QEMUClock *clock)
@@ -482,7 +491,7 @@ static void qemu_run_timers(QEMUClock *clock)
     if (!clock->enabled)
         return;
 
-    current_time = qemu_get_clock (clock);
+    current_time = qemu_get_clock_ns(clock);
     ptimer_head = &active_timers[clock->type];
     for(;;) {
         ts = *ptimer_head;
@@ -559,7 +568,7 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
 
     expire_time = qemu_get_be64(f);
     if (expire_time != -1) {
-        qemu_mod_timer(ts, expire_time);
+        qemu_mod_timer_ns(ts, expire_time);
     } else {
         qemu_del_timer(ts);
     }
@@ -717,7 +726,7 @@ static int64_t qemu_next_alarm_deadline(void)
             delta = hdelta;
     }
     if (active_timers[QEMU_CLOCK_REALTIME]) {
-        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time * 1000000 -
+        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
                  qemu_get_clock_ns(rt_clock));
         if (rtdelta < delta)
             delta = rtdelta;
diff --git a/qemu-timer.h b/qemu-timer.h
index 345feea..0ea77fb 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -41,7 +41,8 @@ int64_t qemu_get_clock(QEMUClock *clock);
 int64_t qemu_get_clock_ns(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
 
-QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque);
+QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
+                          QEMUTimerCB *cb, void *opaque);
 void qemu_free_timer(QEMUTimer *ts);
 void qemu_del_timer(QEMUTimer *ts);
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
@@ -61,15 +62,13 @@ void quit_timers(void);
 static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
                                            void *opaque)
 {
-    assert(clock != rt_clock);
-    return qemu_new_timer(clock, cb, opaque);
+    return qemu_new_timer(clock, SCALE_NS, cb, opaque);
 }
 
 static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
                                            void *opaque)
 {
-    assert(clock == rt_clock);
-    return qemu_new_timer(clock, cb, opaque);
+    return qemu_new_timer(clock, SCALE_MS, cb, opaque);
 }
 
 static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
commit 74475455442398a64355428b37422d14ccc293cb
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 11 16:47:48 2011 +0100

    change all other clock references to use nanosecond resolution accessors
    
    This was done with:
    
        sed -i 's/qemu_get_clock\>/qemu_get_clock_ns/' \
            $(git grep -l 'qemu_get_clock\>' )
        sed -i 's/qemu_new_timer\>/qemu_new_timer_ns/' \
            $(git grep -l 'qemu_new_timer\>' )
    
    after checking that get_clock and new_timer never occur twice
    on the same line.  There were no missed occurrences; however, even
    if there had been, they would have been caught by the compiler.
    
    There was exactly one false positive in qemu_run_timers:
    
         -    current_time = qemu_get_clock (clock);
         +    current_time = qemu_get_clock_ns (clock);
    
    which is of course not in this patch.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/audio/audio.c b/audio/audio.c
index 1729c0b..50d2b64 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1114,7 +1114,7 @@ static int audio_is_timer_needed (void)
 static void audio_reset_timer (AudioState *s)
 {
     if (audio_is_timer_needed ()) {
-        qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
+        qemu_mod_timer (s->ts, qemu_get_clock_ns (vm_clock) + 1);
     }
     else {
         qemu_del_timer (s->ts);
@@ -1820,7 +1820,7 @@ static void audio_init (void)
     QLIST_INIT (&s->cap_head);
     atexit (audio_atexit);
 
-    s->ts = qemu_new_timer (vm_clock, audio_timer, s);
+    s->ts = qemu_new_timer_ns (vm_clock, audio_timer, s);
     if (!s->ts) {
         hw_error("Could not create audio timer\n");
     }
diff --git a/audio/noaudio.c b/audio/noaudio.c
index 0304094..54958f8 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -46,7 +46,7 @@ static int no_run_out (HWVoiceOut *hw, int live)
     int64_t ticks;
     int64_t bytes;
 
-    now = qemu_get_clock (vm_clock);
+    now = qemu_get_clock_ns (vm_clock);
     ticks = now - no->old_ticks;
     bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
     bytes = audio_MIN (bytes, INT_MAX);
@@ -102,7 +102,7 @@ static int no_run_in (HWVoiceIn *hw)
     int samples = 0;
 
     if (dead) {
-        int64_t now = qemu_get_clock (vm_clock);
+        int64_t now = qemu_get_clock_ns (vm_clock);
         int64_t ticks = now - no->old_ticks;
         int64_t bytes =
             muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index a5c0d6b..f972110 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -81,7 +81,7 @@ static void spice_audio_fini (void *opaque)
 static void rate_start (SpiceRateCtl *rate)
 {
     memset (rate, 0, sizeof (*rate));
-    rate->start_ticks = qemu_get_clock (vm_clock);
+    rate->start_ticks = qemu_get_clock_ns (vm_clock);
 }
 
 static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
@@ -91,7 +91,7 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
     int64_t bytes;
     int64_t samples;
 
-    now = qemu_get_clock (vm_clock);
+    now = qemu_get_clock_ns (vm_clock);
     ticks = now - rate->start_ticks;
     bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
     samples = (bytes - rate->bytes_sent) >> info->shift;
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index c522be4..294f357 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -52,7 +52,7 @@ static int wav_run_out (HWVoiceOut *hw, int live)
     int rpos, decr, samples;
     uint8_t *dst;
     struct st_sample *src;
-    int64_t now = qemu_get_clock (vm_clock);
+    int64_t now = qemu_get_clock_ns (vm_clock);
     int64_t ticks = now - wav->old_ticks;
     int64_t bytes =
         muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 5bbc2b5..0b2bc97 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -85,7 +85,7 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
     return d & 0xffffff;
 }
 
@@ -93,7 +93,7 @@ static int get_pmsts(PIIX4PMState *s)
 {
     int64_t d;
 
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
                  get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
         s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
@@ -149,7 +149,7 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
             pmsts = get_pmsts(s);
             if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
                              get_ticks_per_sec());
                 s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
             }
@@ -413,7 +413,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
-    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
+    s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
 
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
diff --git a/hw/adlib.c b/hw/adlib.c
index 1d8092b..4d76d57 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -166,7 +166,7 @@ static void timer_handler (int c, double interval_Sec)
     s->ticking[n] = 1;
 #ifdef DEBUG
     interval = get_ticks_per_sec() * interval_Sec;
-    exp = qemu_get_clock (vm_clock) + interval;
+    exp = qemu_get_clock_ns (vm_clock) + interval;
     s->exp[n] = exp;
 #endif
 
diff --git a/hw/apic.c b/hw/apic.c
index 218d1bb..9febf40 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -641,7 +641,7 @@ static uint32_t apic_get_current_count(APICState *s)
 {
     int64_t d;
     uint32_t val;
-    d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >>
+    d = (qemu_get_clock_ns(vm_clock) - s->initial_count_load_time) >>
         s->count_shift;
     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
         /* periodic */
@@ -865,12 +865,12 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
             int n = index - 0x32;
             s->lvt[n] = val;
             if (n == APIC_LVT_TIMER)
-                apic_timer_update(s, qemu_get_clock(vm_clock));
+                apic_timer_update(s, qemu_get_clock_ns(vm_clock));
         }
         break;
     case 0x38:
         s->initial_count = val;
-        s->initial_count_load_time = qemu_get_clock(vm_clock);
+        s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
         apic_timer_update(s, s->initial_count_load_time);
         break;
     case 0x39:
@@ -1005,7 +1005,7 @@ static int apic_init1(SysBusDevice *dev)
                                             DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MSI_ADDR_SIZE, apic_io_memory);
 
-    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
+    s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
     s->idx = last_apic_idx++;
     local_apics[s->idx] = s;
     return 0;
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 799b007..a759430 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -118,7 +118,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
     case 0x58: /* BOOTCS */
         return 0;
     case 0x5c: /* 24MHz */
-        return muldiv64(qemu_get_clock(vm_clock), 24000000, get_ticks_per_sec());
+        return muldiv64(qemu_get_clock_ns(vm_clock), 24000000, get_ticks_per_sec());
     case 0x60: /* MISC */
         return 0;
     case 0x84: /* PROCID0 */
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 6c7ce01..ffe16b8 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -64,7 +64,7 @@ static inline int64_t systick_scale(nvic_state *s)
 static void systick_reload(nvic_state *s, int reset)
 {
     if (reset)
-        s->systick.tick = qemu_get_clock(vm_clock);
+        s->systick.tick = qemu_get_clock_ns(vm_clock);
     s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
     qemu_mod_timer(s->systick.timer, s->systick.tick);
 }
@@ -136,7 +136,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
             int64_t t;
             if ((s->systick.control & SYSTICK_ENABLE) == 0)
                 return 0;
-            t = qemu_get_clock(vm_clock);
+            t = qemu_get_clock_ns(vm_clock);
             if (t >= s->systick.tick)
                 return 0;
             val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
@@ -273,7 +273,7 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
         s->systick.control &= 0xfffffff8;
         s->systick.control |= value & 7;
         if ((oldval ^ value) & SYSTICK_ENABLE) {
-            int64_t now = qemu_get_clock(vm_clock);
+            int64_t now = qemu_get_clock_ns(vm_clock);
             if (value & SYSTICK_ENABLE) {
                 if (s->systick.tick) {
                     s->systick.tick += now;
@@ -396,7 +396,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 
     gic_init(&s->gic);
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
-    s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
+    s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
     return 0;
 }
diff --git a/hw/baum.c b/hw/baum.c
index 21326ae..2aaf5ff 100644
--- a/hw/baum.c
+++ b/hw/baum.c
@@ -335,7 +335,7 @@ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
         int i;
 
         /* Allow 100ms to complete the DisplayData packet */
-        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock(vm_clock) +
+        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) +
                        get_ticks_per_sec() / 10);
         for (i = 0; i < baum->x * baum->y ; i++) {
             EAT(c);
@@ -604,7 +604,7 @@ CharDriverState *chr_baum_init(QemuOpts *opts)
         goto fail_handle;
     }
 
-    baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
+    baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
 
     if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
         brlapi_perror("baum_init: brlapi_getDisplaySize");
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 982577d..65ffa37 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -88,7 +88,7 @@ static inline void csrhci_fifo_wake(struct csrhci_s *s)
     }
 
     if (s->out_len)
-        qemu_mod_timer(s->out_tm, qemu_get_clock(vm_clock) + s->baud_delay);
+        qemu_mod_timer(s->out_tm, qemu_get_clock_ns(vm_clock) + s->baud_delay);
 }
 
 #define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
@@ -446,7 +446,7 @@ CharDriverState *uart_hci_init(qemu_irq wakeup)
     s->hci->evt_recv = csrhci_out_hci_packet_event;
     s->hci->acl_recv = csrhci_out_hci_packet_acl;
 
-    s->out_tm = qemu_new_timer(vm_clock, csrhci_out_tick, s);
+    s->out_tm = qemu_new_timer_ns(vm_clock, csrhci_out_tick, s);
     s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
     csrhci_reset(s);
 
diff --git a/hw/bt-hci.c b/hw/bt-hci.c
index f1ee92c..41df24c 100644
--- a/hw/bt-hci.c
+++ b/hw/bt-hci.c
@@ -576,7 +576,7 @@ static void bt_hci_inquiry_result(struct bt_hci_s *hci,
 
 static void bt_hci_mod_timer_1280ms(QEMUTimer *timer, int period)
 {
-    qemu_mod_timer(timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(timer, qemu_get_clock_ns(vm_clock) +
                    muldiv64(period << 7, get_ticks_per_sec(), 100));
 }
 
@@ -657,7 +657,7 @@ static void bt_hci_lmp_link_establish(struct bt_hci_s *hci,
     if (master) {
         link->acl_mode = acl_active;
         hci->lm.handle[hci->lm.last_handle].acl_mode_timer =
-                qemu_new_timer(vm_clock, bt_hci_mode_tick, link);
+                qemu_new_timer_ns(vm_clock, bt_hci_mode_tick, link);
     }
 }
 
@@ -1084,7 +1084,7 @@ static int bt_hci_mode_change(struct bt_hci_s *hci, uint16_t handle,
 
     bt_hci_event_status(hci, HCI_SUCCESS);
 
-    qemu_mod_timer(link->acl_mode_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(link->acl_mode_timer, qemu_get_clock_ns(vm_clock) +
                    muldiv64(interval * 625, get_ticks_per_sec(), 1000000));
     bt_hci_lmp_mode_change_master(hci, link->link, mode, interval);
 
@@ -2145,10 +2145,10 @@ struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net)
 {
     struct bt_hci_s *s = qemu_mallocz(sizeof(struct bt_hci_s));
 
-    s->lm.inquiry_done = qemu_new_timer(vm_clock, bt_hci_inquiry_done, s);
-    s->lm.inquiry_next = qemu_new_timer(vm_clock, bt_hci_inquiry_next, s);
+    s->lm.inquiry_done = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_done, s);
+    s->lm.inquiry_next = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_next, s);
     s->conn_accept_timer =
-            qemu_new_timer(vm_clock, bt_hci_conn_accept_timeout, s);
+            qemu_new_timer_ns(vm_clock, bt_hci_conn_accept_timeout, s);
 
     s->evt_packet = bt_hci_evt_packet;
     s->evt_submit = bt_hci_evt_submit;
diff --git a/hw/cuda.c b/hw/cuda.c
index e4c178d..37aa3f4 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -170,7 +170,7 @@ static unsigned int get_counter(CUDATimer *s)
     int64_t d;
     unsigned int counter;
 
-    d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
+    d = muldiv64(qemu_get_clock_ns(vm_clock) - s->load_time,
                  CUDA_TIMER_FREQ, get_ticks_per_sec());
     if (s->index == 0) {
         /* the timer goes down from latch to -1 (period of latch + 2) */
@@ -189,7 +189,7 @@ static unsigned int get_counter(CUDATimer *s)
 static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
 {
     CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
-    ti->load_time = qemu_get_clock(vm_clock);
+    ti->load_time = qemu_get_clock_ns(vm_clock);
     ti->counter_value = val;
     cuda_timer_update(s, ti, ti->load_time);
 }
@@ -346,7 +346,7 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         break;
     case 4:
         s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
-        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+        cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
         break;
     case 5:
         s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
@@ -355,12 +355,12 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         break;
     case 6:
         s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
-        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+        cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
         break;
     case 7:
         s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
         s->ifr &= ~T1_INT;
-        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+        cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
         break;
     case 8:
         s->timers[1].latch = val;
@@ -374,7 +374,7 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         break;
     case 11:
         s->acr = val;
-        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+        cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
         cuda_update(s);
         break;
     case 12:
@@ -506,7 +506,7 @@ static void cuda_adb_poll(void *opaque)
         cuda_send_packet_to_host(s, obuf, olen + 2);
     }
     qemu_mod_timer(s->adb_poll_timer,
-                   qemu_get_clock(vm_clock) +
+                   qemu_get_clock_ns(vm_clock) +
                    (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
 }
 
@@ -524,7 +524,7 @@ static void cuda_receive_packet(CUDAState *s,
             s->autopoll = autopoll;
             if (autopoll) {
                 qemu_mod_timer(s->adb_poll_timer,
-                               qemu_get_clock(vm_clock) +
+                               qemu_get_clock_ns(vm_clock) +
                                (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
             } else {
                 qemu_del_timer(s->adb_poll_timer);
@@ -536,14 +536,14 @@ static void cuda_receive_packet(CUDAState *s,
         break;
     case CUDA_SET_TIME:
         ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
-        s->tick_offset = ti - (qemu_get_clock(vm_clock) / get_ticks_per_sec());
+        s->tick_offset = ti - (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
         obuf[0] = CUDA_PACKET;
         obuf[1] = 0;
         obuf[2] = 0;
         cuda_send_packet_to_host(s, obuf, 3);
         break;
     case CUDA_GET_TIME:
-        ti = s->tick_offset + (qemu_get_clock(vm_clock) / get_ticks_per_sec());
+        ti = s->tick_offset + (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
         obuf[0] = CUDA_PACKET;
         obuf[1] = 0;
         obuf[2] = 0;
@@ -754,14 +754,14 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
     s->irq = irq;
 
     s->timers[0].index = 0;
-    s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
+    s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
 
     s->timers[1].index = 1;
 
     qemu_get_timedate(&tm, 0);
     s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
 
-    s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
+    s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
     *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
                                              DEVICE_NATIVE_ENDIAN);
     register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index 0ef8abe..c332dd5 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -290,7 +290,7 @@ static void set_next_tick(dp8393xState *s)
     }
 
     ticks = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
-    s->wt_last_update = qemu_get_clock(vm_clock);
+    s->wt_last_update = qemu_get_clock_ns(vm_clock);
     delay = get_ticks_per_sec() * ticks / 5000000;
     qemu_mod_timer(s->watchdog, s->wt_last_update + delay);
 }
@@ -305,7 +305,7 @@ static void update_wt_regs(dp8393xState *s)
         return;
     }
 
-    elapsed = s->wt_last_update - qemu_get_clock(vm_clock);
+    elapsed = s->wt_last_update - qemu_get_clock_ns(vm_clock);
     val = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
     val -= elapsed / 5000000;
     s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
@@ -895,7 +895,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     s->memory_rw = memory_rw;
     s->it_shift = it_shift;
     s->irq = irq;
-    s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s);
+    s->watchdog = qemu_new_timer_ns(vm_clock, dp8393x_watchdog, s);
     s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
 
     memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(s->conf.macaddr));
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index 133741b..b08e574 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -85,7 +85,7 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
         r = ptimer_get_count(t->ptimer_t1);
         break;
     case R_TIME:
-        r = qemu_get_clock(vm_clock) / 10;
+        r = qemu_get_clock_ns(vm_clock) / 10;
         break;
     case RW_INTR_MASK:
         r = t->rw_intr_mask;
diff --git a/hw/fdc.c b/hw/fdc.c
index 9f4779c..9fdbc75 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1423,7 +1423,7 @@ static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
     /* XXX: should set main status register to busy */
     cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
     qemu_mod_timer(fdctrl->result_timer,
-                   qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 50));
+                   qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 50));
 }
 
 static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
@@ -1830,7 +1830,7 @@ static int fdctrl_init_common(FDCtrl *fdctrl)
     FLOPPY_DPRINTF("init controller\n");
     fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
     fdctrl->fifo_size = 512;
-    fdctrl->result_timer = qemu_new_timer(vm_clock,
+    fdctrl->result_timer = qemu_new_timer_ns(vm_clock,
                                           fdctrl_result_timer, fdctrl);
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
diff --git a/hw/hpet.c b/hw/hpet.c
index 91ebb75..ef9a2a0 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -143,7 +143,7 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
 
 static uint64_t hpet_get_ticks(HPETState *s)
 {
-    return ns_to_ticks(qemu_get_clock(vm_clock) + s->hpet_offset);
+    return ns_to_ticks(qemu_get_clock_ns(vm_clock) + s->hpet_offset);
 }
 
 /*
@@ -224,7 +224,7 @@ static int hpet_post_load(void *opaque, int version_id)
     HPETState *s = opaque;
 
     /* Recalculate the offset between the main counter and guest time */
-    s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+    s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock_ns(vm_clock);
 
     /* Push number of timers into capability returned via HPET_ID */
     s->capability &= ~HPET_ID_NUM_TIM_MASK;
@@ -298,11 +298,11 @@ static void hpet_timer(void *opaque)
         }
         diff = hpet_calculate_diff(t, cur_tick);
         qemu_mod_timer(t->qemu_timer,
-                       qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
+                       qemu_get_clock_ns(vm_clock) + (int64_t)ticks_to_ns(diff));
     } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
         if (t->wrap_flag) {
             diff = hpet_calculate_diff(t, cur_tick);
-            qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock) +
+            qemu_mod_timer(t->qemu_timer, qemu_get_clock_ns(vm_clock) +
                            (int64_t)ticks_to_ns(diff));
             t->wrap_flag = 0;
         }
@@ -331,7 +331,7 @@ static void hpet_set_timer(HPETTimer *t)
         }
     }
     qemu_mod_timer(t->qemu_timer,
-                   qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
+                   qemu_get_clock_ns(vm_clock) + (int64_t)ticks_to_ns(diff));
 }
 
 static void hpet_del_timer(HPETTimer *t)
@@ -547,7 +547,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Enable main counter and interrupt generation. */
                 s->hpet_offset =
-                    ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+                    ticks_to_ns(s->hpet_counter) - qemu_get_clock_ns(vm_clock);
                 for (i = 0; i < s->num_timers; i++) {
                     if ((&s->timer[i])->cmp != ~0ULL) {
                         hpet_set_timer(&s->timer[i]);
@@ -703,7 +703,7 @@ static int hpet_init(SysBusDevice *dev)
     }
     for (i = 0; i < HPET_MAX_TIMERS; i++) {
         timer = &s->timer[i];
-        timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
+        timer->qemu_timer = qemu_new_timer_ns(vm_clock, hpet_timer, timer);
         timer->tn = i;
         timer->state = s;
     }
diff --git a/hw/i8254.c b/hw/i8254.c
index 47c9d73..a9ca9f6 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -69,7 +69,7 @@ static int pit_get_count(PITChannelState *s)
     uint64_t d;
     int counter;
 
-    d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ,
+    d = muldiv64(qemu_get_clock_ns(vm_clock) - s->count_load_time, PIT_FREQ,
                  get_ticks_per_sec());
     switch(s->mode) {
     case 0:
@@ -198,7 +198,7 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
     case 5:
         if (s->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = qemu_get_clock(vm_clock);
+            s->count_load_time = qemu_get_clock_ns(vm_clock);
             pit_irq_timer_update(s, s->count_load_time);
         }
         break;
@@ -206,7 +206,7 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
     case 3:
         if (s->gate < val) {
             /* restart counting on rising edge */
-            s->count_load_time = qemu_get_clock(vm_clock);
+            s->count_load_time = qemu_get_clock_ns(vm_clock);
             pit_irq_timer_update(s, s->count_load_time);
         }
         /* XXX: disable/enable counting */
@@ -240,7 +240,7 @@ static inline void pit_load_count(PITChannelState *s, int val)
 {
     if (val == 0)
         val = 0x10000;
-    s->count_load_time = qemu_get_clock(vm_clock);
+    s->count_load_time = qemu_get_clock_ns(vm_clock);
     s->count = val;
     pit_irq_timer_update(s, s->count_load_time);
 }
@@ -274,7 +274,7 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                     if (!(val & 0x10) && !s->status_latched) {
                         /* status latch */
                         /* XXX: add BCD and null count */
-                        s->status =  (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
+                        s->status =  (pit_get_out1(s, qemu_get_clock_ns(vm_clock)) << 7) |
                             (s->rw_mode << 4) |
                             (s->mode << 1) |
                             s->bcd;
@@ -513,7 +513,7 @@ static int pit_initfn(ISADevice *dev)
 
     s = &pit->channels[0];
     /* the timer 0 is connected to an IRQ */
-    s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
+    s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
     s->irq = isa_get_irq(pit->irq);
 
     register_ioport_write(pit->iobase, 4, 1, pit_ioport_write, pit);
diff --git a/hw/i8259.c b/hw/i8259.c
index a8dbee6..84d330d 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -202,7 +202,7 @@ static void i8259_set_irq(void *opaque, int irq, int level)
 #endif
 #ifdef DEBUG_IRQ_LATENCY
     if (level) {
-        irq_time[irq] = qemu_get_clock(vm_clock);
+        irq_time[irq] = qemu_get_clock_ns(vm_clock);
     }
 #endif
     pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
@@ -255,7 +255,7 @@ int pic_read_irq(PicState2 *s)
 #ifdef DEBUG_IRQ_LATENCY
     printf("IRQ%d latency=%0.3fus\n",
            irq,
-           (double)(qemu_get_clock(vm_clock) -
+           (double)(qemu_get_clock_ns(vm_clock) -
                     irq_time[irq]) * 1000000.0 / get_ticks_per_sec());
 #endif
     DPRINTF("pic_interrupt: irq=%d\n", irq);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 9c91a49..294d237 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -598,7 +598,7 @@ void ide_sector_write(IDEState *s)
            option _only_ to install Windows 2000. You must disable it
            for normal use. */
         qemu_mod_timer(s->sector_write_timer,
-                       qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 1000));
+                       qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 1000));
     } else {
         ide_set_irq(s->bus);
     }
@@ -2570,7 +2570,7 @@ static void ide_init1(IDEBus *bus, int unit)
     s->io_buffer = qemu_memalign(2048, IDE_DMA_BUF_SECTORS*512 + 4);
     s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
     s->smart_selftest_data = qemu_blockalign(s->bs, 512);
-    s->sector_write_timer = qemu_new_timer(vm_clock,
+    s->sector_write_timer = qemu_new_timer_ns(vm_clock,
                                            ide_sector_write_timer_cb, s);
 }
 
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index b2b6708..b0b1d12 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1126,7 +1126,7 @@ static void intel_hda_reset(DeviceState *dev)
     HDACodecDevice *cdev;
 
     intel_hda_regs_reset(d);
-    d->wall_base_ns = qemu_get_clock(vm_clock);
+    d->wall_base_ns = qemu_get_clock_ns(vm_clock);
 
     /* reset codecs */
     QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 9cc7952..af6949f 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -327,7 +327,7 @@ static void lan9118_reset(DeviceState *d)
     s->afc_cfg = 0;
     s->e2p_cmd = 0;
     s->e2p_data = 0;
-    s->free_timer_start = qemu_get_clock(vm_clock) / 40;
+    s->free_timer_start = qemu_get_clock_ns(vm_clock) / 40;
 
     ptimer_stop(s->timer);
     ptimer_set_count(s->timer, 0xffff);
@@ -1070,7 +1070,7 @@ static uint32_t lan9118_readl(void *opaque, target_phys_addr_t offset)
     case CSR_WORD_SWAP:
         return s->word_swap;
     case CSR_FREE_RUN:
-        return (qemu_get_clock(vm_clock) / 40) - s->free_timer_start;
+        return (qemu_get_clock_ns(vm_clock) / 40) - s->free_timer_start;
     case CSR_RX_DROP:
         /* TODO: Implement dropped frames counter.  */
         return 0;
diff --git a/hw/lm832x.c b/hw/lm832x.c
index ce7dcac..590a4cc 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -463,9 +463,9 @@ static int lm8323_init(i2c_slave *i2c)
     LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
 
     s->model = 0x8323;
-    s->pwm.tm[0] = qemu_new_timer(vm_clock, lm_kbd_pwm0_tick, s);
-    s->pwm.tm[1] = qemu_new_timer(vm_clock, lm_kbd_pwm1_tick, s);
-    s->pwm.tm[2] = qemu_new_timer(vm_clock, lm_kbd_pwm2_tick, s);
+    s->pwm.tm[0] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm0_tick, s);
+    s->pwm.tm[1] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm1_tick, s);
+    s->pwm.tm[2] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm2_tick, s);
     qdev_init_gpio_out(&i2c->qdev, &s->nirq, 1);
 
     lm_kbd_reset(s);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 2020487..9f39d6b 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -123,7 +123,7 @@ static void alarm_cb (void *opaque)
         /* Repeat once a second */
         next_time = 1;
     }
-    qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock_ns(vm_clock) +
                     next_time * 1000);
     qemu_set_irq(NVRAM->IRQ, 0);
 }
@@ -691,8 +691,8 @@ static void m48t59_init_common(M48t59State *s)
 {
     s->buffer = qemu_mallocz(s->size);
     if (s->type == 59) {
-        s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
-        s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
+        s->alrm_timer = qemu_new_timer_ns(vm_clock, &alarm_cb, s);
+        s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s);
     }
     qemu_get_timedate(&s->alarm, 0);
 
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index a1b0e31..1c9a706 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -112,7 +112,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
     } else {
         /* divide each RTC interval to 2 - 8 smaller intervals */
         int c = MIN(s->irq_coalesced, 7) + 1; 
-        int64_t next_clock = qemu_get_clock(rtc_clock) +
+        int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
             muldiv64(s->period / c, get_ticks_per_sec(), 32768);
         qemu_mod_timer(s->coalesced_timer, next_clock);
     }
@@ -234,7 +234,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
-            rtc_timer_update(s, qemu_get_clock(rtc_clock));
+            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_B:
             if (data & REG_B_SET) {
@@ -256,7 +256,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             } else {
                 s->cmos_data[RTC_REG_B] = data;
             }
-            rtc_timer_update(s, qemu_get_clock(rtc_clock));
+            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_C:
         case RTC_REG_D:
@@ -599,17 +599,17 @@ static int rtc_initfn(ISADevice *dev)
 
     rtc_set_date_from_host(dev);
 
-    s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
+    s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
 #ifdef TARGET_I386
     if (rtc_td_hack)
         s->coalesced_timer =
-            qemu_new_timer(rtc_clock, rtc_coalesced_timer, s);
+            qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
 #endif
-    s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
-    s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
+    s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
+    s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
 
     s->next_second_time =
-        qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
+        qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
     qemu_mod_timer(s->second_timer2, s->next_second_time);
 
     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index 9c95f28..cf6ac69 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -47,7 +47,7 @@ static void cpu_mips_timer_update(CPUState *env)
     uint64_t now, next;
     uint32_t wait;
 
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     wait = env->CP0_Compare - env->CP0_Count -
 	    (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
     next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
@@ -71,7 +71,7 @@ uint32_t cpu_mips_get_count (CPUState *env)
     } else {
         uint64_t now;
 
-        now = qemu_get_clock(vm_clock);
+        now = qemu_get_clock_ns(vm_clock);
         if (qemu_timer_pending(env->timer)
             && qemu_timer_expired(env->timer, now)) {
             /* The timer has already expired.  */
@@ -90,7 +90,7 @@ void cpu_mips_store_count (CPUState *env, uint32_t count)
     else {
         /* Store new count register */
         env->CP0_Count =
-            count - (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+            count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
                                        TIMER_FREQ, get_ticks_per_sec());
         /* Update timer timer */
         cpu_mips_timer_update(env);
@@ -115,7 +115,7 @@ void cpu_mips_start_count(CPUState *env)
 void cpu_mips_stop_count(CPUState *env)
 {
     /* Store the current value */
-    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
                                          TIMER_FREQ, get_ticks_per_sec());
 }
 
@@ -141,7 +141,7 @@ static void mips_timer_cb (void *opaque)
 
 void cpu_mips_clock_init (CPUState *env)
 {
-    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
+    env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
     env->CP0_Compare = 0;
     cpu_mips_store_count(env, 1);
 }
diff --git a/hw/mpcore.c b/hw/mpcore.c
index fc05215..379065a 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -63,7 +63,7 @@ static void mpcore_timer_reload(mpcore_timer_state *s, int restart)
     if (s->count == 0)
         return;
     if (restart)
-        s->tick = qemu_get_clock(vm_clock);
+        s->tick = qemu_get_clock_ns(vm_clock);
     s->tick += (int64_t)s->count * mpcore_timer_scale(s);
     qemu_mod_timer(s->timer, s->tick);
 }
@@ -92,7 +92,7 @@ static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset)
         if (((s->control & 1) == 0) || (s->count == 0))
             return 0;
         /* Slow and ugly, but hopefully won't happen too often.  */
-        val = s->tick - qemu_get_clock(vm_clock);
+        val = s->tick - qemu_get_clock_ns(vm_clock);
         val /= mpcore_timer_scale(s);
         if (val < 0)
             val = 0;
@@ -145,7 +145,7 @@ static void mpcore_timer_init(mpcore_priv_state *mpcore,
 {
     s->id = id;
     s->mpcore = mpcore;
-    s->timer = qemu_new_timer(vm_clock, mpcore_timer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, mpcore_timer_tick, s);
 }
 
 
diff --git a/hw/omap1.c b/hw/omap1.c
index f2be4de..364c26f 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -101,7 +101,7 @@ struct omap_mpu_timer_s {
 
 static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
 {
-    uint64_t distance = qemu_get_clock(vm_clock) - timer->time;
+    uint64_t distance = qemu_get_clock_ns(vm_clock) - timer->time;
 
     if (timer->st && timer->enable && timer->rate)
         return timer->val - muldiv64(distance >> (timer->ptv + 1),
@@ -113,7 +113,7 @@ static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
 static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
 {
     timer->val = omap_timer_read(timer);
-    timer->time = qemu_get_clock(vm_clock);
+    timer->time = qemu_get_clock_ns(vm_clock);
 }
 
 static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
@@ -258,7 +258,7 @@ static struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
 
     s->irq = irq;
     s->clk = clk;
-    s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, s);
     s->tick = qemu_bh_new(omap_timer_fire, s);
     omap_mpu_timer_reset(s);
     omap_timer_clk_setup(s);
@@ -382,7 +382,7 @@ static struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
 
     s->timer.irq = irq;
     s->timer.clk = clk;
-    s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
+    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
     omap_wd_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
@@ -484,7 +484,7 @@ static struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
 
     s->timer.irq = irq;
     s->timer.clk = clk;
-    s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
+    s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
     omap_os_timer_reset(s);
     omap_timer_clk_setup(&s->timer);
 
@@ -580,7 +580,7 @@ static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
     case 0x10:	/* GAUGING_CTRL */
         /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
         if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
-            now = qemu_get_clock(vm_clock);
+            now = qemu_get_clock_ns(vm_clock);
 
             if (value & 1)
                 s->ulpd_gauge_start = now;
@@ -2915,7 +2915,7 @@ static void omap_mcbsp_source_tick(void *opaque)
     s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
 
     omap_mcbsp_rx_newdata(s);
-    qemu_mod_timer(s->source_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(s->source_timer, qemu_get_clock_ns(vm_clock) +
                    get_ticks_per_sec());
 }
 
@@ -2961,7 +2961,7 @@ static void omap_mcbsp_sink_tick(void *opaque)
     s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
 
     omap_mcbsp_tx_newdata(s);
-    qemu_mod_timer(s->sink_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(s->sink_timer, qemu_get_clock_ns(vm_clock) +
                    get_ticks_per_sec());
 }
 
@@ -3344,8 +3344,8 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
     s->rxirq = irq[1];
     s->txdrq = dma[0];
     s->rxdrq = dma[1];
-    s->sink_timer = qemu_new_timer(vm_clock, omap_mcbsp_sink_tick, s);
-    s->source_timer = qemu_new_timer(vm_clock, omap_mcbsp_source_tick, s);
+    s->sink_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_sink_tick, s);
+    s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
     omap_mcbsp_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_mcbsp_readfn,
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index 9c0f9f2..f2a424f 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -102,7 +102,7 @@ static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
     uint64_t distance;
 
     if (timer->st && timer->rate) {
-        distance = qemu_get_clock(vm_clock) - timer->time;
+        distance = qemu_get_clock_ns(vm_clock) - timer->time;
         distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
 
         if (distance >= 0xffffffff - timer->val)
@@ -117,7 +117,7 @@ static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
 {
     if (timer->st) {
         timer->val = omap_gp_timer_read(timer);
-        timer->time = qemu_get_clock(vm_clock);
+        timer->time = qemu_get_clock_ns(vm_clock);
     }
 }
 
@@ -163,7 +163,7 @@ static void omap_gp_timer_tick(void *opaque)
         timer->val = 0;
     } else {
         timer->val = timer->load_val;
-        timer->time = qemu_get_clock(vm_clock);
+        timer->time = qemu_get_clock_ns(vm_clock);
     }
 
     if (timer->trigger == gpt_trigger_overflow ||
@@ -411,7 +411,7 @@ static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
         break;
 
     case 0x28:	/* TCRR */
-        s->time = qemu_get_clock(vm_clock);
+        s->time = qemu_get_clock_ns(vm_clock);
         s->val = value;
         omap_gp_timer_update(s);
         break;
@@ -421,7 +421,7 @@ static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
         break;
 
     case 0x30:	/* TTGR */
-        s->time = qemu_get_clock(vm_clock);
+        s->time = qemu_get_clock_ns(vm_clock);
         s->val = s->load_val;
         omap_gp_timer_update(s);
         break;
@@ -470,8 +470,8 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
     s->ta = ta;
     s->irq = irq;
     s->clk = fclk;
-    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
-    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
+    s->timer = qemu_new_timer_ns(vm_clock, omap_gp_timer_tick, s);
+    s->match = qemu_new_timer_ns(vm_clock, omap_gp_timer_match, s);
     s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
     omap_gp_timer_reset(s);
     omap_gp_timer_clk_setup(s);
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index 118668a..67f65e6 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -27,7 +27,7 @@ struct omap_synctimer_s {
 
 /* 32-kHz Sync Timer of the OMAP2 */
 static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
-    return muldiv64(qemu_get_clock(vm_clock), 0x8000, get_ticks_per_sec());
+    return muldiv64(qemu_get_clock_ns(vm_clock), 0x8000, get_ticks_per_sec());
 }
 
 void omap_synctimer_reset(struct omap_synctimer_s *s)
diff --git a/hw/pcnet.c b/hw/pcnet.c
index d3d5661..82ccbbd 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1336,7 +1336,7 @@ static void pcnet_poll_timer(void *opaque)
     pcnet_update_irq(s);
 
     if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
-        uint64_t now = qemu_get_clock(vm_clock) * 33;
+        uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
         if (!s->timer || !now)
             s->timer = now;
         else {
@@ -1348,7 +1348,7 @@ static void pcnet_poll_timer(void *opaque)
                 CSR_POLL(s) = t;
         }
         qemu_mod_timer(s->poll_timer,
-            pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
+            pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
     }
 }
 
@@ -1726,7 +1726,7 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
     int i;
     uint16_t checksum;
 
-    s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
+    s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
diff --git a/hw/pcspk.c b/hw/pcspk.c
index 5f02908..7fa2d36 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -118,7 +118,7 @@ static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
     int out;
 
     s->dummy_refresh_clock ^= (1 << 4);
-    out = pit_get_out(s->pit, 2, qemu_get_clock(vm_clock)) << 5;
+    out = pit_get_out(s->pit, 2, qemu_get_clock_ns(vm_clock)) << 5;
 
     return pit_get_gate(s->pit, 2) | (s->data_on << 1) | s->dummy_refresh_clock | out;
 }
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index fb20dfb..90fdc84 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -628,7 +628,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
 #else
     pfl->ro = 0;
 #endif
-    pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
+    pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
     pfl->base = base;
     pfl->sector_len = sector_len;
     pfl->total_len = total_len;
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 3594a36..30c8aa4 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -390,7 +390,7 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
             pflash_update(pfl, 0, pfl->chip_len);
             /* Let's wait 5 seconds before chip erase is done */
             qemu_mod_timer(pfl->timer,
-                           qemu_get_clock(vm_clock) + (get_ticks_per_sec() * 5));
+                           qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 5));
             break;
         case 0x30:
             /* Sector erase */
@@ -403,7 +403,7 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
             pfl->status = 0x00;
             /* Let's wait 1/2 second before sector erase is done */
             qemu_mod_timer(pfl->timer,
-                           qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 2));
+                           qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 2));
             break;
         default:
             DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
@@ -647,7 +647,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 #else
     pfl->ro = 0;
 #endif
-    pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
+    pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
     pfl->sector_len = sector_len;
     pfl->width = width;
     pfl->wcycle = 0;
diff --git a/hw/pl031.c b/hw/pl031.c
index c488f69..8c2f9d0 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -80,9 +80,9 @@ static void pl031_interrupt(void * opaque)
 
 static uint32_t pl031_get_count(pl031_state *s)
 {
-    /* This assumes qemu_get_clock returns the time since the machine was
+    /* This assumes qemu_get_clock_ns returns the time since the machine was
        created.  */
-    return s->tick_offset + qemu_get_clock(vm_clock) / get_ticks_per_sec();
+    return s->tick_offset + qemu_get_clock_ns(vm_clock) / get_ticks_per_sec();
 }
 
 static void pl031_set_alarm(pl031_state *s)
@@ -90,7 +90,7 @@ static void pl031_set_alarm(pl031_state *s)
     int64_t now;
     uint32_t ticks;
 
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     ticks = s->tick_offset + now / get_ticks_per_sec();
 
     /* The timer wraps around.  This subtraction also wraps in the same way,
@@ -217,7 +217,7 @@ static int pl031_init(SysBusDevice *dev)
     qemu_get_timedate(&tm, 0);
     s->tick_offset = mktimegm(&tm);
 
-    s->timer = qemu_new_timer(vm_clock, pl031_interrupt, s);
+    s->timer = qemu_new_timer_ns(vm_clock, pl031_interrupt, s);
     return 0;
 }
 
diff --git a/hw/ppc.c b/hw/ppc.c
index de02d33..b55a848 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -419,7 +419,7 @@ uint64_t cpu_ppc_load_tbl (CPUState *env)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
 
     return tb;
@@ -430,7 +430,7 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
 
     return tb >> 32;
@@ -454,9 +454,9 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
     tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
                      &tb_env->tb_offset, tb | (uint64_t)value);
 }
 
@@ -465,9 +465,9 @@ static inline void _cpu_ppc_store_tbu(CPUState *env, uint32_t value)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
     tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
                      &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
 }
 
@@ -481,7 +481,7 @@ uint64_t cpu_ppc_load_atbl (CPUState *env)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
 
     return tb;
@@ -492,7 +492,7 @@ uint32_t cpu_ppc_load_atbu (CPUState *env)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
 
     return tb >> 32;
@@ -503,9 +503,9 @@ void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
     tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
                      &tb_env->atb_offset, tb | (uint64_t)value);
 }
 
@@ -514,9 +514,9 @@ void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
     tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
                      &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
 }
 
@@ -527,7 +527,7 @@ static void cpu_ppc_tb_stop (CPUState *env)
 
     /* If the time base is already frozen, do nothing */
     if (tb_env->tb_freq != 0) {
-        vmclk = qemu_get_clock(vm_clock);
+        vmclk = qemu_get_clock_ns(vm_clock);
         /* Get the time base */
         tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
         /* Get the alternate time base */
@@ -549,7 +549,7 @@ static void cpu_ppc_tb_start (CPUState *env)
 
     /* If the time base is not frozen, do nothing */
     if (tb_env->tb_freq == 0) {
-        vmclk = qemu_get_clock(vm_clock);
+        vmclk = qemu_get_clock_ns(vm_clock);
         /* Get the time base from tb_offset */
         tb = tb_env->tb_offset;
         /* Get the alternate time base from atb_offset */
@@ -569,7 +569,7 @@ static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
     uint32_t decr;
     int64_t diff;
 
-    diff = next - qemu_get_clock(vm_clock);
+    diff = next - qemu_get_clock_ns(vm_clock);
     if (diff >= 0)
         decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
     else
@@ -598,7 +598,7 @@ uint64_t cpu_ppc_load_purr (CPUState *env)
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t diff;
 
-    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
+    diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
 
     return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
 }
@@ -631,7 +631,7 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
 
     LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
                 decr, value);
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
     if (is_excp)
         next += *nextp - now;
@@ -692,7 +692,7 @@ void cpu_ppc_store_purr (CPUState *env, uint64_t value)
     ppc_tb_t *tb_env = env->tb_env;
 
     tb_env->purr_load = value;
-    tb_env->purr_start = qemu_get_clock(vm_clock);
+    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
 }
 
 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
@@ -719,11 +719,11 @@ clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
     tb_env = qemu_mallocz(sizeof(ppc_tb_t));
     env->tb_env = tb_env;
     /* Create new timer */
-    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
     if (0) {
         /* XXX: find a suitable condition to enable the hypervisor decrementer
          */
-        tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
+        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
     } else {
         tb_env->hdecr_timer = NULL;
     }
@@ -787,7 +787,7 @@ static void cpu_4xx_fit_cb (void *opaque)
     env = opaque;
     tb_env = env->tb_env;
     ppcemb_timer = tb_env->opaque;
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
     case 0:
         next = 1 << 9;
@@ -833,7 +833,7 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
     } else {
         LOG_TB("%s: start PIT %016" PRIx64 "\n",
                     __func__, ppcemb_timer->pit_reload);
-        now = qemu_get_clock(vm_clock);
+        now = qemu_get_clock_ns(vm_clock);
         next = now + muldiv64(ppcemb_timer->pit_reload,
                               get_ticks_per_sec(), tb_env->decr_freq);
         if (is_excp)
@@ -877,7 +877,7 @@ static void cpu_4xx_wdt_cb (void *opaque)
     env = opaque;
     tb_env = env->tb_env;
     ppcemb_timer = tb_env->opaque;
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
     case 0:
         next = 1 << 17;
@@ -1002,11 +1002,11 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq,
     LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
     if (ppcemb_timer != NULL) {
         /* We use decr timer for PIT */
-        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
+        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
         ppcemb_timer->fit_timer =
-            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
         ppcemb_timer->wdt_timer =
-            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
         ppcemb_timer->decr_excp = decr_excp;
     }
 
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 334187e..2ce79ee 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -1347,7 +1347,7 @@ static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr)
     switch (addr) {
     case 0x00:
         /* Time base counter */
-        ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset,
+        ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
                        gpt->tb_freq, get_ticks_per_sec());
         break;
     case 0x10:
@@ -1404,7 +1404,7 @@ static void ppc4xx_gpt_writel (void *opaque,
     case 0x00:
         /* Time base counter */
         gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
-            - qemu_get_clock(vm_clock);
+            - qemu_get_clock_ns(vm_clock);
         ppc4xx_gpt_compute_timer(gpt);
         break;
     case 0x10:
@@ -1501,7 +1501,7 @@ static void ppc4xx_gpt_init(target_phys_addr_t base, qemu_irq irqs[5])
     for (i = 0; i < 5; i++) {
         gpt->irqs[i] = irqs[i];
     }
-    gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt);
+    gpt->timer = qemu_new_timer_ns(vm_clock, &ppc4xx_gpt_cb, gpt);
 #ifdef DEBUG_GPT
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index d86a283..5615ef9 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -105,7 +105,7 @@ static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
 {
 #if 0
     int out;
-    out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
+    out = pit_get_out(pit, 2, qemu_get_clock_ns(vm_clock));
     dummy_refresh_clock ^= 1;
     return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
         (dummy_refresh_clock << 4);
diff --git a/hw/ptimer.c b/hw/ptimer.c
index 4ddbc59..e68c1d1 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -68,7 +68,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
     uint64_t counter;
 
     if (s->enabled) {
-        now = qemu_get_clock(vm_clock);
+        now = qemu_get_clock_ns(vm_clock);
         /* Figure out the current counter value.  */
         if (now - s->next_event > 0
             || s->period == 0) {
@@ -122,7 +122,7 @@ void ptimer_set_count(ptimer_state *s, uint64_t count)
 {
     s->delta = count;
     if (s->enabled) {
-        s->next_event = qemu_get_clock(vm_clock);
+        s->next_event = qemu_get_clock_ns(vm_clock);
         ptimer_reload(s);
     }
 }
@@ -137,7 +137,7 @@ void ptimer_run(ptimer_state *s, int oneshot)
         return;
     }
     s->enabled = oneshot ? 2 : 1;
-    s->next_event = qemu_get_clock(vm_clock);
+    s->next_event = qemu_get_clock_ns(vm_clock);
     ptimer_reload(s);
 }
 
@@ -159,7 +159,7 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
     s->period = period;
     s->period_frac = 0;
     if (s->enabled) {
-        s->next_event = qemu_get_clock(vm_clock);
+        s->next_event = qemu_get_clock_ns(vm_clock);
         ptimer_reload(s);
     }
 }
@@ -170,7 +170,7 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
     s->period = 1000000000ll / freq;
     s->period_frac = (1000000000ll << 32) / freq;
     if (s->enabled) {
-        s->next_event = qemu_get_clock(vm_clock);
+        s->next_event = qemu_get_clock_ns(vm_clock);
         ptimer_reload(s);
     }
 }
@@ -183,7 +183,7 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
     if (reload)
         s->delta = limit;
     if (s->enabled && reload) {
-        s->next_event = qemu_get_clock(vm_clock);
+        s->next_event = qemu_get_clock_ns(vm_clock);
         ptimer_reload(s);
     }
 }
@@ -239,6 +239,6 @@ ptimer_state *ptimer_init(QEMUBH *bh)
 
     s = (ptimer_state *)qemu_mallocz(sizeof(ptimer_state));
     s->bh = bh;
-    s->timer = qemu_new_timer(vm_clock, ptimer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, ptimer_tick, s);
     return s;
 }
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index d75a817..9b95e2c 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -372,7 +372,7 @@ static uint32_t pxa2xx_perf_read(void *opaque, int op2, int reg, int crm)
         return s->pmnc;
     case CPCCNT:
         if (s->pmnc & 1)
-            return qemu_get_clock(vm_clock);
+            return qemu_get_clock_ns(vm_clock);
         else
             return 0;
     case CPINTEN:
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 1242f82..f777a21 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -171,7 +171,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
             goto badreg;
         return s->tm4[tm].tm.value;
     case OSCR:
-        return s->clock + muldiv64(qemu_get_clock(vm_clock) -
+        return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
                         s->lastload, s->freq, get_ticks_per_sec());
     case OSCR11: tm ++;
     case OSCR10: tm ++;
@@ -187,7 +187,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
             if (s->tm4[tm - 1].freq)
                 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
-                                qemu_get_clock(vm_clock) -
+                                qemu_get_clock_ns(vm_clock) -
                                 s->tm4[tm - 1].lastload,
                                 s->tm4[tm - 1].freq, get_ticks_per_sec());
             else
@@ -196,7 +196,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 
         if (!s->tm4[tm].freq)
             return s->tm4[tm].clock;
-        return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
+        return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
                         s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
     case OIER:
         return s->irq_enabled;
@@ -237,7 +237,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     case OSMR1:  tm ++;
     case OSMR0:
         s->timer[tm].value = value;
-        pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
+        pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
         break;
     case OSMR11: tm ++;
     case OSMR10: tm ++;
@@ -250,11 +250,11 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
         if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].tm.value = value;
-        pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+        pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
         break;
     case OSCR:
         s->oldclock = s->clock;
-        s->lastload = qemu_get_clock(vm_clock);
+        s->lastload = qemu_get_clock_ns(vm_clock);
         s->clock = value;
         pxa2xx_timer_update(s, s->lastload);
         break;
@@ -269,7 +269,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
         if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].oldclock = s->tm4[tm].clock;
-        s->tm4[tm].lastload = qemu_get_clock(vm_clock);
+        s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
         s->tm4[tm].clock = value;
         pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
         break;
@@ -300,7 +300,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
             s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
         else {
             s->tm4[tm].freq = 0;
-            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
         }
         break;
     case OMCR11: tm ++;
@@ -316,7 +316,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                     pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
         else {
             s->tm4[tm].freq = 0;
-            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
         }
         break;
     default:
@@ -363,7 +363,7 @@ static void pxa2xx_timer_tick4(void *opaque)
     if (t->control & (1 << 3))
         t->clock = 0;
     if (t->control & (1 << 6))
-        pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
+        pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
     if (i->events & 0xff0)
         qemu_irq_raise(i->irq4);
 }
@@ -374,7 +374,7 @@ static int pxa25x_timer_post_load(void *opaque, int version_id)
     int64_t now;
     int i;
 
-    now = qemu_get_clock(vm_clock);
+    now = qemu_get_clock_ns(vm_clock);
     pxa2xx_timer_update(s, now);
 
     if (pxa2xx_timer_has_tm4(s))
@@ -394,7 +394,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
     s->irq_enabled = 0;
     s->oldclock = 0;
     s->clock = 0;
-    s->lastload = qemu_get_clock(vm_clock);
+    s->lastload = qemu_get_clock_ns(vm_clock);
     s->reset3 = 0;
 
     for (i = 0; i < 4; i ++) {
@@ -402,7 +402,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->timer[i].irq);
         s->timer[i].info = s;
         s->timer[i].num = i;
-        s->timer[i].qtimer = qemu_new_timer(vm_clock,
+        s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
                         pxa2xx_timer_tick, &s->timer[i]);
     }
     if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
@@ -414,7 +414,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
             s->tm4[i].tm.num = i + 4;
             s->tm4[i].freq = 0;
             s->tm4[i].control = 0x0;
-            s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
+            s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
                         pxa2xx_timer_tick4, &s->tm4[i]);
         }
     }
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 0a9d98d..d30230a 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -104,7 +104,7 @@ static void set_next_tick(rc4030State *s)
 
     tm_hz = 1000 / (s->itr + 1);
 
-    qemu_mod_timer(s->periodic_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(s->periodic_timer, qemu_get_clock_ns(vm_clock) +
                    get_ticks_per_sec() / tm_hz);
 }
 
@@ -811,7 +811,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     *irqs = qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
     *dmas = rc4030_allocate_dmas(s, 4);
 
-    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
+    s->periodic_timer = qemu_new_timer_ns(vm_clock, rc4030_periodic_timer, s);
     s->timer_irq = timer;
     s->jazz_bus_irq = jazz_bus;
 
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 7a87522..0ba51fc 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2517,7 +2517,7 @@ static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
 
     s->IntrMask = val;
 
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
     rtl8139_update_irq(s);
 
 }
@@ -2558,7 +2558,7 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
      * and probably emulated is slower is better to assume this resetting was
      * done before testing on previous rtl8139_update_irq lead to IRQ loosing
      */
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
     rtl8139_update_irq(s);
 
 #endif
@@ -2566,7 +2566,7 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
 
 static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
 {
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
 
     uint32_t ret = s->IntrStatus;
 
@@ -2831,7 +2831,7 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
 
         case Timer:
             DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
-            s->TCTR_base = qemu_get_clock(vm_clock);
+            s->TCTR_base = qemu_get_clock_ns(vm_clock);
             rtl8139_set_next_tctr_time(s, s->TCTR_base);
             break;
 
@@ -2839,7 +2839,7 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
             DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val));
             if (s->TimerInt != val) {
                 s->TimerInt = val;
-                rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+                rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
             }
             break;
 
@@ -3050,7 +3050,7 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
             break;
 
         case Timer:
-            ret = muldiv64(qemu_get_clock(vm_clock) - s->TCTR_base,
+            ret = muldiv64(qemu_get_clock_ns(vm_clock) - s->TCTR_base,
                            PCI_FREQUENCY, get_ticks_per_sec());
             DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
             break;
@@ -3144,7 +3144,7 @@ static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
 static int rtl8139_post_load(void *opaque, int version_id)
 {
     RTL8139State* s = opaque;
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
     if (version_id < 4) {
         s->cplus_enabled = s->CpCmd != 0;
     }
@@ -3170,7 +3170,7 @@ static const VMStateDescription vmstate_rtl8139_hotplug_ready ={
 static void rtl8139_pre_save(void *opaque)
 {
     RTL8139State* s = opaque;
-    int64_t current_time = qemu_get_clock(vm_clock);
+    int64_t current_time = qemu_get_clock_ns(vm_clock);
 
     /* set IntrStatus correctly */
     rtl8139_set_next_tctr_time(s, current_time);
@@ -3319,7 +3319,7 @@ static void rtl8139_timer(void *opaque)
 
     s->IntrStatus |= PCSTimeout;
     rtl8139_update_irq(s);
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
 }
 
 static void rtl8139_cleanup(VLANClientState *nc)
@@ -3400,8 +3400,8 @@ static int pci_rtl8139_init(PCIDevice *dev)
     s->cplus_txbuffer_offset = 0;
 
     s->TimerExpire = 0;
-    s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
-    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+    s->timer = qemu_new_timer_ns(vm_clock, rtl8139_timer, s);
+    rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
 
     add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet-phy at 0");
 
diff --git a/hw/sb16.c b/hw/sb16.c
index c9d37ad..a76df1b 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -766,7 +766,7 @@ static void complete (SB16State *s)
                     if (s->aux_ts) {
                         qemu_mod_timer (
                             s->aux_ts,
-                            qemu_get_clock (vm_clock) + ticks
+                            qemu_get_clock_ns (vm_clock) + ticks
                             );
                     }
                 }
@@ -1361,7 +1361,7 @@ static int sb16_initfn (ISADevice *dev)
     s->csp_regs[9] = 0xf8;
 
     reset_mixer (s);
-    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
+    s->aux_ts = qemu_new_timer_ns (vm_clock, aux_timer, s);
     if (!s->aux_ts) {
         dolog ("warning: Could not create auxiliary timer\n");
     }
diff --git a/hw/serial.c b/hw/serial.c
index 879237f..0ee61dd 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -312,13 +312,13 @@ static void serial_update_msl(SerialState *s)
        We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */
 
     if (s->poll_msl)
-        qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + get_ticks_per_sec() / 100);
+        qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
 }
 
 static void serial_xmit(void *opaque)
 {
     SerialState *s = opaque;
-    uint64_t new_xmit_ts = qemu_get_clock(vm_clock);
+    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
 
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
@@ -350,7 +350,7 @@ static void serial_xmit(void *opaque)
         s->tsr_retry = 0;
     }
 
-    s->last_xmit_ts = qemu_get_clock(vm_clock);
+    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
     if (!(s->lsr & UART_LSR_THRE))
         qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time);
 
@@ -494,7 +494,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                 qemu_chr_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
                 /* Update the modem status after a one-character-send wait-time, since there may be a response
                    from the device/computer at the other end of the serial line */
-                qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + s->char_transmit_time);
+                qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + s->char_transmit_time);
             }
         }
         break;
@@ -525,7 +525,7 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
                 if (s->recv_fifo.count == 0)
                     s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
                 else
-                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4);
+                    qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
                 s->timeout_ipending = 0;
             } else {
                 ret = s->rbr;
@@ -641,7 +641,7 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size)
         }
         s->lsr |= UART_LSR_DR;
         /* call the timeout receive callback in 4 char transmit time */
-        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4);
+        qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
     } else {
         if (s->lsr & UART_LSR_DR)
             s->lsr |= UART_LSR_OE;
@@ -720,7 +720,7 @@ static void serial_reset(void *opaque)
     fifo_clear(s,RECV_FIFO);
     fifo_clear(s,XMIT_FIFO);
 
-    s->last_xmit_ts = qemu_get_clock(vm_clock);
+    s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
 
     s->thr_ipending = 0;
     s->last_break_enable = 0;
@@ -734,10 +734,10 @@ static void serial_init_core(SerialState *s)
 	exit(1);
     }
 
-    s->modem_status_poll = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
+    s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
 
-    s->fifo_timeout_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
-    s->transmit_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_xmit, s);
+    s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
+    s->transmit_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_xmit, s);
 
     qemu_register_reset(serial_reset, s);
 
diff --git a/hw/soc_dma.c b/hw/soc_dma.c
index 23ec516..3f0f414 100644
--- a/hw/soc_dma.c
+++ b/hw/soc_dma.c
@@ -84,7 +84,7 @@ struct dma_s {
 
 static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes)
 {
-    int64_t now = qemu_get_clock(vm_clock);
+    int64_t now = qemu_get_clock_ns(vm_clock);
     struct dma_s *dma = (struct dma_s *) ch->dma;
 
     qemu_mod_timer(ch->timer, now + delay_bytes / dma->channel_freq);
@@ -246,7 +246,7 @@ struct soc_dma_s *soc_dma_init(int n)
     for (i = 0; i < n; i ++) {
         s->ch[i].dma = &s->soc;
         s->ch[i].num = i;
-        s->ch[i].timer = qemu_new_timer(vm_clock, soc_dma_ch_run, &s->ch[i]);
+        s->ch[i].timer = qemu_new_timer_ns(vm_clock, soc_dma_ch_run, &s->ch[i]);
     }
 
     soc_dma_reset(&s->soc);
diff --git a/hw/spitz.c b/hw/spitz.c
index 5b1e42d..006f7a9 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -393,7 +393,7 @@ static void spitz_keyboard_tick(void *opaque)
             s->fifopos = 0;
     }
 
-    qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
                    get_ticks_per_sec() / 32);
 }
 
@@ -485,7 +485,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
         qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
                 qdev_get_gpio_in(dev, i));
 
-    qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock));
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock));
 
     qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
 }
@@ -506,7 +506,7 @@ static int spitz_keyboard_init(SysBusDevice *dev)
 
     spitz_keyboard_pre_map(s);
 
-    s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
+    s->kbdtimer = qemu_new_timer_ns(vm_clock, spitz_keyboard_tick, s);
     qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
     qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5d8bd55..0d52926 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -79,7 +79,7 @@ static void gptm_reload(gptm_state *s, int n, int reset)
 {
     int64_t tick;
     if (reset)
-        tick = qemu_get_clock(vm_clock);
+        tick = qemu_get_clock_ns(vm_clock);
     else
         tick = s->tick[n];
 
@@ -353,8 +353,8 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     s->opaque[0] = s->opaque[1] = s;
-    s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
-    s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
+    s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
+    s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
     register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
                     gptm_save, gptm_load, s);
     return 0;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index d282324..dbb5a15 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -352,9 +352,9 @@ static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
     timer->disabled_mask = disabled_mask;
 
     timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock(vm_clock);
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
 
-    timer->qtimer = qemu_new_timer(vm_clock, cb, env);
+    timer->qtimer = qemu_new_timer_ns(vm_clock, cb, env);
 
     return timer;
 }
@@ -362,7 +362,7 @@ static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
 static void cpu_timer_reset(CPUTimer *timer)
 {
     timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock(vm_clock);
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
 
     qemu_del_timer(timer->qtimer);
 }
@@ -457,7 +457,7 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
     uint64_t real_count = count & ~timer->disabled_mask;
     uint64_t disabled_bit = count & timer->disabled_mask;
 
-    int64_t vm_clock_offset = qemu_get_clock(vm_clock) -
+    int64_t vm_clock_offset = qemu_get_clock_ns(vm_clock) -
                     cpu_to_timer_ticks(real_count, timer->frequency);
 
     TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
@@ -471,7 +471,7 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
 uint64_t cpu_tick_get_count(CPUTimer *timer)
 {
     uint64_t real_count = timer_to_cpu_ticks(
-                    qemu_get_clock(vm_clock) - timer->clock_offset,
+                    qemu_get_clock_ns(vm_clock) - timer->clock_offset,
                     timer->frequency);
 
     TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
@@ -486,7 +486,7 @@ uint64_t cpu_tick_get_count(CPUTimer *timer)
 
 void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
 {
-    int64_t now = qemu_get_clock(vm_clock);
+    int64_t now = qemu_get_clock_ns(vm_clock);
 
     uint64_t real_limit = limit & ~timer->disabled_mask;
     timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 329aa42..16d8f9e 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -66,7 +66,7 @@ static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t v
     offset &= 0xfff;
     switch (offset >> 2) {
     case RTC_LATCH:
-        now = qemu_get_clock(vm_clock);
+        now = qemu_get_clock_ns(vm_clock);
         if (value >= 4) {
             s->offset = s->data - now;
         } else {
diff --git a/hw/tsc2005.c b/hw/tsc2005.c
index a55853c..c95dcf0 100644
--- a/hw/tsc2005.c
+++ b/hw/tsc2005.c
@@ -290,7 +290,7 @@ static void tsc2005_pin_update(TSC2005State *s)
     s->precision = s->nextprecision;
     s->function = s->nextfunction;
     s->pdst = !s->pnd0;	/* Synchronised on internal clock */
-    expires = qemu_get_clock(vm_clock) + (get_ticks_per_sec() >> 7);
+    expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 7);
     qemu_mod_timer(s->timer, expires);
 }
 
@@ -529,7 +529,7 @@ void *tsc2005_init(qemu_irq pintdav)
     s->y = 240;
     s->pressure = 0;
     s->precision = s->nextprecision = 0;
-    s->timer = qemu_new_timer(vm_clock, tsc2005_timer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, tsc2005_timer_tick, s);
     s->pint = pintdav;
     s->model = 0x2005;
 
diff --git a/hw/tsc210x.c b/hw/tsc210x.c
index fca73f1..96446dd 100644
--- a/hw/tsc210x.c
+++ b/hw/tsc210x.c
@@ -503,9 +503,9 @@ static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg)
         l_ch = 1;
         r_ch = 1;
         if (s->softstep && !(s->dac_power & (1 << 10))) {
-            l_ch = (qemu_get_clock(vm_clock) >
+            l_ch = (qemu_get_clock_ns(vm_clock) >
                             s->volume_change + TSC_SOFTSTEP_DELAY);
-            r_ch = (qemu_get_clock(vm_clock) >
+            r_ch = (qemu_get_clock_ns(vm_clock) >
                             s->volume_change + TSC_SOFTSTEP_DELAY);
         }
 
@@ -514,7 +514,7 @@ static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg)
     case 0x05:	/* Stereo DAC Power Control */
         return 0x2aa0 | s->dac_power |
                 (((s->dac_power & (1 << 10)) &&
-                  (qemu_get_clock(vm_clock) >
+                  (qemu_get_clock_ns(vm_clock) >
                    s->powerdown + TSC_POWEROFF_DELAY)) << 6);
 
     case 0x06:	/* Audio Control 3 */
@@ -695,7 +695,7 @@ static void tsc2102_audio_register_write(
 
     case 0x02:	/* DAC Volume Control */
         s->volume = value;
-        s->volume_change = qemu_get_clock(vm_clock);
+        s->volume_change = qemu_get_clock_ns(vm_clock);
         return;
 
     case 0x03:
@@ -717,7 +717,7 @@ static void tsc2102_audio_register_write(
 
     case 0x05:	/* Stereo DAC Power Control */
         if ((value & ~s->dac_power) & (1 << 10))
-            s->powerdown = qemu_get_clock(vm_clock);
+            s->powerdown = qemu_get_clock_ns(vm_clock);
 
         s->dac_power = value & 0x9543;
 #ifdef TSC_VERBOSE
@@ -864,7 +864,7 @@ static void tsc210x_pin_update(TSC210xState *s)
     s->busy = 1;
     s->precision = s->nextprecision;
     s->function = s->nextfunction;
-    expires = qemu_get_clock(vm_clock) + (get_ticks_per_sec() >> 10);
+    expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 10);
     qemu_mod_timer(s->timer, expires);
 }
 
@@ -1005,7 +1005,7 @@ static void tsc210x_i2s_set_rate(TSC210xState *s, int in, int out)
 static void tsc210x_save(QEMUFile *f, void *opaque)
 {
     TSC210xState *s = (TSC210xState *) opaque;
-    int64_t now = qemu_get_clock(vm_clock);
+    int64_t now = qemu_get_clock_ns(vm_clock);
     int i;
 
     qemu_put_be16(f, s->x);
@@ -1051,7 +1051,7 @@ static void tsc210x_save(QEMUFile *f, void *opaque)
 static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
 {
     TSC210xState *s = (TSC210xState *) opaque;
-    int64_t now = qemu_get_clock(vm_clock);
+    int64_t now = qemu_get_clock_ns(vm_clock);
     int i;
 
     s->x = qemu_get_be16(f);
@@ -1111,7 +1111,7 @@ uWireSlave *tsc2102_init(qemu_irq pint)
     s->y = 160;
     s->pressure = 0;
     s->precision = s->nextprecision = 0;
-    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
     s->pint = pint;
     s->model = 0x2102;
     s->name = "tsc2102";
@@ -1160,7 +1160,7 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
     s->y = 240;
     s->pressure = 0;
     s->precision = s->nextprecision = 0;
-    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+    s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
     s->pint = penirq;
     s->kbint = kbirq;
     s->davint = dav;
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 0005e1c..ccd01ad 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -520,7 +520,7 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
     case TUSB_DEV_OTG_TIMER:
         s->otg_timer_val = value;
         if (value & TUSB_DEV_OTG_TIMER_ENABLE)
-            qemu_mod_timer(s->otg_timer, qemu_get_clock(vm_clock) +
+            qemu_mod_timer(s->otg_timer, qemu_get_clock_ns(vm_clock) +
                             muldiv64(TUSB_DEV_OTG_TIMER_VAL(value),
                                      get_ticks_per_sec(), TUSB_DEVCLOCK));
         else
@@ -742,8 +742,8 @@ TUSBState *tusb6010_init(qemu_irq intr)
     s->iomemtype[1] = cpu_register_io_memory(tusb_async_readfn,
                     tusb_async_writefn, s, DEVICE_NATIVE_ENDIAN);
     s->irq = intr;
-    s->otg_timer = qemu_new_timer(vm_clock, tusb_otg_tick, s);
-    s->pwr_timer = qemu_new_timer(vm_clock, tusb_power_tick, s);
+    s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
+    s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
     s->musb = musb_init(qemu_allocate_irqs(tusb_musb_core_intr, s,
                             __musb_irq_max));
 
@@ -761,6 +761,6 @@ void tusb6010_power(TUSBState *s, int on)
         s->intr_ok = 0;
         tusb_intr_update(s);
         qemu_mod_timer(s->pwr_timer,
-                       qemu_get_clock(vm_clock) + get_ticks_per_sec() / 2);
+                       qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 2);
     }
 }
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 79b20df..c25362c 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -796,7 +796,7 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
         break;
     case SET_IDLE:
         s->idle = (uint8_t) (value >> 8);
-        usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
+        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
         ret = 0;
         break;
     default:
@@ -815,7 +815,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
     switch(p->pid) {
     case USB_TOKEN_IN:
         if (p->devep == 1) {
-            int64_t curtime = qemu_get_clock(vm_clock);
+            int64_t curtime = qemu_get_clock_ns(vm_clock);
             if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
                 return USB_RET_NAK;
             usb_hid_set_next_idle(s, curtime);
@@ -900,7 +900,7 @@ static int usb_hid_post_load(void *opaque, int version_id)
     USBHIDState *s = opaque;
 
     if (s->idle) {
-        usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
+        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
     }
     return 0;
 }
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 782cfa2..15bc549 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -513,9 +513,9 @@ static inline void musb_schedule_cb(USBPacket *packey, void *opaque, int dir)
         return musb_cb_tick(opaque);
 
     if (!ep->intv_timer[dir])
-        ep->intv_timer[dir] = qemu_new_timer(vm_clock, musb_cb_tick, opaque);
+        ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, opaque);
 
-    qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock(vm_clock) +
+    qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
                    muldiv64(timeout, get_ticks_per_sec(), 8000));
 }
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 09ea0b6..d2b14f7 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1101,7 +1101,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
 /* Generate a SOF event, and set a timer for EOF */
 static void ohci_sof(OHCIState *ohci)
 {
-    ohci->sof_time = qemu_get_clock(vm_clock);
+    ohci->sof_time = qemu_get_clock_ns(vm_clock);
     qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
     ohci_set_interrupt(ohci, OHCI_INTR_SF);
 }
@@ -1186,12 +1186,12 @@ static void ohci_frame_boundary(void *opaque)
  */
 static int ohci_bus_start(OHCIState *ohci)
 {
-    ohci->eof_timer = qemu_new_timer(vm_clock,
+    ohci->eof_timer = qemu_new_timer_ns(vm_clock,
                     ohci_frame_boundary,
                     ohci);
 
     if (ohci->eof_timer == NULL) {
-        fprintf(stderr, "usb-ohci: %s: qemu_new_timer failed\n", ohci->name);
+        fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
         /* TODO: Signal unrecoverable error */
         return 0;
     }
@@ -1311,7 +1311,7 @@ static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
     /* Being in USB operational state guarnatees sof_time was
      * set already.
      */
-    tks = qemu_get_clock(vm_clock) - ohci->sof_time;
+    tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
 
     /* avoid muldiv if possible */
     if (tks >= usb_frame_time)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index b384e1d..346db3e 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -441,7 +441,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     case 0x00:
         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
             /* start frame processing */
-            qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
+            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
             s->status &= ~UHCI_STS_HCHALTED;
         } else if (!(val & UHCI_CMD_RS)) {
             s->status |= UHCI_STS_HCHALTED;
@@ -1133,8 +1133,8 @@ static int usb_uhci_common_initfn(UHCIState *s)
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         usb_port_location(&s->ports[i].port, NULL, i+1);
     }
-    s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
-    s->expire_time = qemu_get_clock(vm_clock) +
+    s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
+    s->expire_time = qemu_get_clock_ns(vm_clock) +
         (get_ticks_per_sec() / FRAME_TIMER_FREQ);
     s->num_ports_vmstate = NB_PORTS;
 
diff --git a/hw/vga.c b/hw/vga.c
index 3ef85fb..124295a 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -260,7 +260,7 @@ static uint8_t vga_precise_retrace(VGACommonState *s)
         int cur_line, cur_line_char, cur_char;
         int64_t cur_tick;
 
-        cur_tick = qemu_get_clock(vm_clock);
+        cur_tick = qemu_get_clock_ns(vm_clock);
 
         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
         cur_line = cur_char / r->htotal;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 5962298..6997e02 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -150,7 +150,7 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
     if (virtio_net_started(n, status) && !n->vhost_started) {
         if (n->tx_timer) {
             qemu_mod_timer(n->tx_timer,
-                           qemu_get_clock(vm_clock) + n->tx_timeout);
+                           qemu_get_clock_ns(vm_clock) + n->tx_timeout);
         } else {
             qemu_bh_schedule(n->tx_bh);
         }
@@ -785,7 +785,7 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
         virtio_net_flush_tx(n, vq);
     } else {
         qemu_mod_timer(n->tx_timer,
-                       qemu_get_clock(vm_clock) + n->tx_timeout);
+                       qemu_get_clock_ns(vm_clock) + n->tx_timeout);
         n->tx_waiting = 1;
         virtio_queue_set_notification(vq, 0);
     }
@@ -1019,7 +1019,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 
     if (net->tx && !strcmp(net->tx, "timer")) {
         n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx_timer);
-        n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
+        n->tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer, n);
         n->tx_timeout = net->txtimer;
     } else {
         n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx_bh);
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index cacc217..818460d 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -186,7 +186,7 @@ typedef struct VT686MC97State {
 static uint32_t get_pmtmr(VT686PMState *s)
 {
     uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
     return d & 0xffffff;
 }
 
@@ -195,7 +195,7 @@ static int get_pmsts(VT686PMState *s)
     int64_t d;
     int pmsts;
     pmsts = s->pmsts;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
         s->pmsts |= TMROF_EN;
     return pmsts;
@@ -238,7 +238,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
             pmsts = get_pmsts(s);
             if (pmsts & val & TMROF_EN) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+                d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
                 s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
             }
             s->pmsts &= ~val;
@@ -486,7 +486,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     apm_init(&s->apm, NULL, s);
 
-    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
+    s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 90bf5f6..4a7fba7 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -129,7 +129,7 @@ static void i6300esb_restart_timer(I6300State *d, int stage)
 
     i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
 
-    qemu_mod_timer(d->timer, qemu_get_clock(vm_clock) + timeout);
+    qemu_mod_timer(d->timer, qemu_get_clock_ns(vm_clock) + timeout);
 }
 
 /* This is called when the guest disables the watchdog. */
@@ -410,7 +410,7 @@ static int i6300esb_init(PCIDevice *dev)
 
     i6300esb_debug("I6300State = %p\n", d);
 
-    d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d);
+    d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d);
     d->previous_reboot_flag = 0;
 
     pci_conf = d->dev.config;
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index 1248464..81f22d0 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -58,7 +58,7 @@ static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data)
     ib700_debug("addr = %x, data = %x\n", addr, data);
 
     timeout = (int64_t) time_map[data & 0xF] * get_ticks_per_sec();
-    qemu_mod_timer(s->timer, qemu_get_clock (vm_clock) + timeout);
+    qemu_mod_timer(s->timer, qemu_get_clock_ns (vm_clock) + timeout);
 }
 
 /* A write (of any value) to this register disables the timer. */
@@ -99,7 +99,7 @@ static int wdt_ib700_init(ISADevice *dev)
 
     ib700_debug("watchdog init\n");
 
-    s->timer = qemu_new_timer(vm_clock, ib700_timer_expired, s);
+    s->timer = qemu_new_timer_ns(vm_clock, ib700_timer_expired, s);
     register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, s);
     register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, s);
 
diff --git a/monitor.c b/monitor.c
index 22ae3bb..413c963 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1873,7 +1873,7 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
         kbd_put_keycode(keycode & 0x7f);
     }
     /* delayed key up events */
-    qemu_mod_timer(key_timer, qemu_get_clock(vm_clock) +
+    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
                    muldiv64(get_ticks_per_sec(), hold_time, 1000));
 }
 
@@ -5157,7 +5157,7 @@ void monitor_init(CharDriverState *chr, int flags)
     Monitor *mon;
 
     if (is_first_init) {
-        key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
+        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
         is_first_init = 0;
     }
 
diff --git a/net/dump.c b/net/dump.c
index 6db7ecf..83eda0f 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -67,7 +67,7 @@ static ssize_t dump_receive(VLANClientState *nc, const uint8_t *buf, size_t size
         return size;
     }
 
-    ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec());
+    ts = muldiv64(qemu_get_clock_ns(vm_clock), 1000000, get_ticks_per_sec());
     caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
 
     hdr.ts.tv_sec = ts / 1000000;
diff --git a/qemu-timer.c b/qemu-timer.c
index 8bea74a..bc818ae 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -242,7 +242,7 @@ static void icount_adjust(void)
         return;
 
     cur_time = cpu_get_clock();
-    cur_icount = qemu_get_clock(vm_clock);
+    cur_icount = qemu_get_clock_ns(vm_clock);
     delta = cur_icount - cur_time;
     /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
     if (delta > 0
@@ -271,7 +271,7 @@ static void icount_adjust_rt(void * opaque)
 static void icount_adjust_vm(void * opaque)
 {
     qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10);
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
     icount_adjust();
 }
 
@@ -604,9 +604,9 @@ void configure_icount(const char *option)
     icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
     qemu_mod_timer(icount_rt_timer,
                    qemu_get_clock_ms(rt_clock) + 1000);
-    icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL);
+    icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
     qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10);
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
 }
 
 void qemu_run_all_timers(void)
@@ -646,7 +646,7 @@ static void host_alarm_handler(int host_signum)
         static int64_t delta_min = INT64_MAX;
         static int64_t delta_max, delta_cum, last_clock, delta, ti;
         static int count;
-        ti = qemu_get_clock(vm_clock);
+        ti = qemu_get_clock_ns(vm_clock);
         if (last_clock != 0) {
             delta = ti - last_clock;
             if (delta < delta_min)
@@ -706,7 +706,7 @@ static int64_t qemu_next_alarm_deadline(void)
 
     if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) {
         delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
-                     qemu_get_clock(vm_clock);
+                     qemu_get_clock_ns(vm_clock);
     } else {
         delta = INT32_MAX;
     }
diff --git a/savevm.c b/savevm.c
index 66f88c6..912b127 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1943,7 +1943,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     sn->date_sec = tv.tv_sec;
     sn->date_nsec = tv.tv_usec * 1000;
 #endif
-    sn->vm_clock_nsec = qemu_get_clock(vm_clock);
+    sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
 
     if (name) {
         ret = bdrv_snapshot_find(bs, old_sn, name);
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index bd4012a..3134590 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -85,7 +85,7 @@ int kvm_arch_init_vcpu(CPUState *cenv)
     sregs.pvr = cenv->spr[SPR_PVR];
     ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
 
-    idle_timer = qemu_new_timer(vm_clock, kvm_kick_env, cenv);
+    idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
 
     return ret;
 }
@@ -246,7 +246,7 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
             printf("cpu %d fail inject %x\n", env->cpu_index, irq);
 
         /* Always wake up soon in case the interrupt was level based */
-        qemu_mod_timer(idle_timer, qemu_get_clock(vm_clock) +
+        qemu_mod_timer(idle_timer, qemu_get_clock_ns(vm_clock) +
                        (get_ticks_per_sec() / 50));
     }
 
diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
index 6f0468c..536fcab 100644
--- a/target-ppc/kvm_ppc.c
+++ b/target-ppc/kvm_ppc.c
@@ -89,7 +89,7 @@ void kvmppc_fdt_update(void *fdt)
 static void kvmppc_timer_hack(void *opaque)
 {
     qemu_service_io();
-    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
 }
 
 void kvmppc_init(void)
@@ -99,7 +99,7 @@ void kvmppc_init(void)
      * run. So, until Qemu gains IO threads, we create this timer to ensure
      * that the device model gets a chance to run. */
     kvmppc_timer_rate = get_ticks_per_sec() / 10;
-    kvmppc_timer = qemu_new_timer(vm_clock, &kvmppc_timer_hack, NULL);
-    qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
+    kvmppc_timer = qemu_new_timer_ns(vm_clock, &kvmppc_timer_hack, NULL);
+    qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
 }
 
commit 7bd427d801e1e3293a634d3c83beadaa90ffb911
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 11 16:47:48 2011 +0100

    change all rt_clock references to use millisecond resolution accessors
    
    This was done with:
    
        sed -i '/get_clock\>.*rt_clock/s/get_clock\>/get_clock_ms/' \
            $(git grep -l 'get_clock\>.*rt_clock' )
        sed -i '/new_timer\>.*rt_clock/s/new_timer\>/new_timer_ms/' \
            $(git grep -l 'new_timer\>.*rt_clock' )
    
    after checking that get_clock and new_timer never occur twice
    on the same line.  There were no missed occurrences; however, even
    if there had been, they would have been caught by the compiler.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/buffered_file.c b/buffered_file.c
index 8435a31..b5e2baf 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -238,7 +238,7 @@ static void buffered_rate_tick(void *opaque)
         return;
     }
 
-    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
+    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
 
     if (s->freeze_output)
         return;
@@ -274,9 +274,9 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque,
                              buffered_set_rate_limit,
 			     buffered_get_rate_limit);
 
-    s->timer = qemu_new_timer(rt_clock, buffered_rate_tick, s);
+    s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);
 
-    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
+    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
 
     return s->file;
 }
diff --git a/console.c b/console.c
index 57d6eb5..12407b3 100644
--- a/console.c
+++ b/console.c
@@ -1135,7 +1135,7 @@ static void kbd_send_chars(void *opaque)
     /* characters are pending: we send them a bit later (XXX:
        horrible, should change char device API) */
     if (s->out_fifo.count > 0) {
-        qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
+        qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
     }
 }
 
@@ -1457,7 +1457,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
 
     s->out_fifo.buf = s->out_fifo_buf;
     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
-    s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
+    s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
     s->ds = ds;
 
     if (!color_inited) {
diff --git a/hw/omap1.c b/hw/omap1.c
index d5e4dab..f2be4de 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2802,7 +2802,7 @@ static void omap_rtc_reset(struct omap_rtc_s *s)
     s->pm_am = 0;
     s->auto_comp = 0;
     s->round = 0;
-    s->tick = qemu_get_clock(rt_clock);
+    s->tick = qemu_get_clock_ms(rt_clock);
     memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
     s->alarm_tm.tm_mday = 0x01;
     s->status = 1 << 7;
@@ -2822,7 +2822,7 @@ static struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
 
     s->irq = irq[0];
     s->alarm = irq[1];
-    s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
+    s->clk = qemu_new_timer_ms(rt_clock, omap_rtc_tick, s);
 
     omap_rtc_reset(s);
 
@@ -3399,9 +3399,9 @@ static void omap_lpg_tick(void *opaque)
     struct omap_lpg_s *s = opaque;
 
     if (s->cycle)
-        qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->period - s->on);
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(rt_clock) + s->period - s->on);
     else
-        qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->on);
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(rt_clock) + s->on);
 
     s->cycle = !s->cycle;
     printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
@@ -3516,7 +3516,7 @@ static struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
     struct omap_lpg_s *s = (struct omap_lpg_s *)
             qemu_mallocz(sizeof(struct omap_lpg_s));
 
-    s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s);
+    s->tm = qemu_new_timer_ms(rt_clock, omap_lpg_tick, s);
 
     omap_lpg_reset(s);
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 4c7b9e6..d75a817 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -921,7 +921,7 @@ static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rt_clock);
     s->last_rcnr += ((rt - s->last_hz) << 15) /
             (1000 * ((s->rttr & 0xffff) + 1));
     s->last_rdcr += ((rt - s->last_hz) << 15) /
@@ -931,7 +931,7 @@ static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rt_clock);
     if (s->rtsr & (1 << 12))
         s->last_swcr += (rt - s->last_sw) / 10;
     s->last_sw = rt;
@@ -939,7 +939,7 @@ static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
 
 static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
 {
-    int64_t rt = qemu_get_clock(rt_clock);
+    int64_t rt = qemu_get_clock_ms(rt_clock);
     if (s->rtsr & (1 << 15))
         s->last_swcr += rt - s->last_pi;
     s->last_pi = rt;
@@ -1064,16 +1064,16 @@ static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
     case PIAR:
         return s->piar;
     case RCNR:
-        return s->last_rcnr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
+        return s->last_rcnr + ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
                 (1000 * ((s->rttr & 0xffff) + 1));
     case RDCR:
-        return s->last_rdcr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
+        return s->last_rdcr + ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
                 (1000 * ((s->rttr & 0xffff) + 1));
     case RYCR:
         return s->last_rycr;
     case SWCR:
         if (s->rtsr & (1 << 12))
-            return s->last_swcr + (qemu_get_clock(rt_clock) - s->last_sw) / 10;
+            return s->last_swcr + (qemu_get_clock_ms(rt_clock) - s->last_sw) / 10;
         else
             return s->last_swcr;
     default:
@@ -1219,14 +1219,14 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
     s->last_swcr = (tm.tm_hour << 19) |
             (tm.tm_min << 13) | (tm.tm_sec << 7);
     s->last_rtcpicr = 0;
-    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock);
-
-    s->rtc_hz    = qemu_new_timer(rt_clock, pxa2xx_rtc_hz_tick,    s);
-    s->rtc_rdal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal1_tick, s);
-    s->rtc_rdal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal2_tick, s);
-    s->rtc_swal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal1_tick, s);
-    s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s);
-    s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
+    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rt_clock);
+
+    s->rtc_hz    = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_hz_tick,    s);
+    s->rtc_rdal1 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_rdal1_tick, s);
+    s->rtc_rdal2 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_rdal2_tick, s);
+    s->rtc_swal1 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_swal1_tick, s);
+    s->rtc_swal2 = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_swal2_tick, s);
+    s->rtc_pi    = qemu_new_timer_ms(rt_clock, pxa2xx_rtc_pi_tick,    s);
 
     sysbus_init_irq(dev, &s->rtc_irq);
 
diff --git a/hw/twl92230.c b/hw/twl92230.c
index e61f17f..8e74acc 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -74,14 +74,14 @@ static inline void menelaus_update(MenelausState *s)
 
 static inline void menelaus_rtc_start(MenelausState *s)
 {
-    s->rtc.next += qemu_get_clock(rt_clock);
+    s->rtc.next += qemu_get_clock_ms(rt_clock);
     qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
 }
 
 static inline void menelaus_rtc_stop(MenelausState *s)
 {
     qemu_del_timer(s->rtc.hz_tm);
-    s->rtc.next -= qemu_get_clock(rt_clock);
+    s->rtc.next -= qemu_get_clock_ms(rt_clock);
     if (s->rtc.next < 1)
         s->rtc.next = 1;
 }
@@ -786,7 +786,7 @@ static void menelaus_pre_save(void *opaque)
 {
     MenelausState *s = opaque;
     /* Should be <= 1000 */
-    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock(rt_clock);
+    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock_ms(rt_clock);
 }
 
 static int menelaus_post_load(void *opaque, int version_id)
@@ -847,7 +847,7 @@ static int twl92230_init(i2c_slave *i2c)
 {
     MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
 
-    s->rtc.hz_tm = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
+    s->rtc.hz_tm = qemu_new_timer_ms(rt_clock, menelaus_rtc_hz, s);
     /* Three output pins plus one interrupt pin.  */
     qdev_init_gpio_out(&i2c->qdev, s->out, 4);
     qdev_init_gpio_in(&i2c->qdev, menelaus_gpio_set, 3);
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index 7f1fd66..371c562 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -149,7 +149,7 @@ static void xen_domain_poll(void *opaque)
         goto quit;
     }
 
-    qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
+    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
     return;
 
 quit:
@@ -291,8 +291,8 @@ int xen_domain_build_pv(const char *kernel, const char *ramdisk,
         goto err;
     }
 
-    xen_poll = qemu_new_timer(rt_clock, xen_domain_poll, NULL);
-    qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
+    xen_poll = qemu_new_timer_ms(rt_clock, xen_domain_poll, NULL);
+    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
     return 0;
 
 err:
diff --git a/qemu-char.c b/qemu-char.c
index cad35d7..31c9e79 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -267,7 +267,7 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
                 int64_t ti;
                 int secs;
 
-                ti = qemu_get_clock(rt_clock);
+                ti = qemu_get_clock_ms(rt_clock);
                 if (d->timestamps_start == -1)
                     d->timestamps_start = ti;
                 ti -= d->timestamps_start;
@@ -911,7 +911,7 @@ static void pty_chr_update_read_handler(CharDriverState *chr)
      * timeout to the normal (much longer) poll interval before the
      * timer triggers.
      */
-    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
+    qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 10);
 }
 
 static void pty_chr_state(CharDriverState *chr, int connected)
@@ -925,7 +925,7 @@ static void pty_chr_state(CharDriverState *chr, int connected)
         /* (re-)connect poll interval for idle guests: once per second.
          * We check more frequently in case the guests sends data to
          * the virtual device linked to our pty. */
-        qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
+        qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 1000);
     } else {
         if (!s->connected)
             qemu_chr_generic_open(chr);
@@ -1001,7 +1001,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     chr->chr_update_read_handler = pty_chr_update_read_handler;
     chr->chr_close = pty_chr_close;
 
-    s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
+    s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
 
     return chr;
 }
diff --git a/qemu-timer.c b/qemu-timer.c
index 1939d6b..8bea74a 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -264,7 +264,7 @@ static void icount_adjust(void)
 static void icount_adjust_rt(void * opaque)
 {
     qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock(rt_clock) + 1000);
+                   qemu_get_clock_ms(rt_clock) + 1000);
     icount_adjust();
 }
 
@@ -601,9 +601,9 @@ void configure_icount(const char *option)
        the virtual time trigger catches emulated time passing too fast.
        Realtime triggers occur even when idle, so use them less frequently
        than VM triggers.  */
-    icount_rt_timer = qemu_new_timer(rt_clock, icount_adjust_rt, NULL);
+    icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
     qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock(rt_clock) + 1000);
+                   qemu_get_clock_ms(rt_clock) + 1000);
     icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL);
     qemu_mod_timer(icount_vm_timer,
                    qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10);
diff --git a/savevm.c b/savevm.c
index 60d2f2a..66f88c6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -137,7 +137,7 @@ static void qemu_announce_self_once(void *opaque)
 
     if (--count) {
         /* delay 50ms, 150ms, 250ms, ... */
-        qemu_mod_timer(timer, qemu_get_clock(rt_clock) +
+        qemu_mod_timer(timer, qemu_get_clock_ms(rt_clock) +
                        50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
     } else {
 	    qemu_del_timer(timer);
@@ -148,7 +148,7 @@ static void qemu_announce_self_once(void *opaque)
 void qemu_announce_self(void)
 {
 	static QEMUTimer *timer;
-	timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
+	timer = qemu_new_timer_ms(rt_clock, qemu_announce_self_once, &timer);
 	qemu_announce_self_once(&timer);
 }
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 332d83b..1593be1 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -393,7 +393,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
     global_writefds = writefds;
     global_xfds = xfds;
 
-    curtime = qemu_get_clock(rt_clock);
+    curtime = qemu_get_clock_ms(rt_clock);
 
     QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
 	/*
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 1aa1a5e..ef56ed6 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -55,14 +55,14 @@ static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque)
     SpiceTimer *timer;
 
     timer = qemu_mallocz(sizeof(*timer));
-    timer->timer = qemu_new_timer(rt_clock, func, opaque);
+    timer->timer = qemu_new_timer_ms(rt_clock, func, opaque);
     QTAILQ_INSERT_TAIL(&timers, timer, next);
     return timer;
 }
 
 static void timer_start(SpiceTimer *timer, uint32_t ms)
 {
-    qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms);
+    qemu_mod_timer(timer->timer, qemu_get_clock_ms(rt_clock) + ms);
 }
 
 static void timer_cancel(SpiceTimer *timer)
diff --git a/ui/vnc.c b/ui/vnc.c
index 1b68965..fdc4a70 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1875,8 +1875,8 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
 
     if (data[0] > 3) {
         vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
-        if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))
-            qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
+        if (!qemu_timer_expired(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval))
+            qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
     }
 
     switch (data[0]) {
@@ -2441,7 +2441,7 @@ static void vnc_refresh(void *opaque)
 
     if (vnc_trylock_display(vd)) {
         vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
-        qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) +
+        qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) +
                        vd->timer_interval);
         return;
     }
@@ -2468,14 +2468,14 @@ static void vnc_refresh(void *opaque)
         if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
             vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
     }
-    qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
+    qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
 }
 
 static void vnc_init_timer(VncDisplay *vd)
 {
     vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
     if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
-        vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
+        vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd);
         vnc_dpy_resize(vd->ds);
         vnc_refresh(vd);
     }
diff --git a/usb-linux.c b/usb-linux.c
index ccf7073..255009f 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1535,12 +1535,12 @@ static void usb_host_auto_check(void *unused)
     }
 
     if (!usb_auto_timer) {
-        usb_auto_timer = qemu_new_timer(rt_clock, usb_host_auto_check, NULL);
+        usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
         if (!usb_auto_timer) {
             return;
         }
     }
-    qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
+    qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
 }
 
 /*
diff --git a/vl.c b/vl.c
index b1a94aa..48150cf 100644
--- a/vl.c
+++ b/vl.c
@@ -1142,7 +1142,7 @@ static void gui_update(void *opaque)
             interval = dcl->gui_timer_interval;
         dcl = dcl->next;
     }
-    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
+    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
 }
 
 static void nographic_update(void *opaque)
@@ -1150,7 +1150,7 @@ static void nographic_update(void *opaque)
     uint64_t interval = GUI_REFRESH_INTERVAL;
 
     qemu_flush_coalesced_mmio_buffer();
-    qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
+    qemu_mod_timer(nographic_timer, interval + qemu_get_clock_ms(rt_clock));
 }
 
 struct vm_change_state_entry {
@@ -3089,15 +3089,15 @@ int main(int argc, char **argv, char **envp)
     dcl = ds->listeners;
     while (dcl != NULL) {
         if (dcl->dpy_refresh != NULL) {
-            ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
-            qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
+            ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
+            qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
             break;
         }
         dcl = dcl->next;
     }
     if (ds->gui_timer == NULL) {
-        nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
-        qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
+        nographic_timer = qemu_new_timer_ms(rt_clock, nographic_update, NULL);
+        qemu_mod_timer(nographic_timer, qemu_get_clock_ms(rt_clock));
     }
     text_consoles_set_display(ds);
 
commit 0ce1b9480ee52b037b99deeffbdac4ae48641d63
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 11 16:46:02 2011 +0100

    add more helper functions with explicit milli/nanosecond resolution
    
    The code doesn't make much sense right now, but it will as
    soon as timers will be able to scale their resolution arbitrarily.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.h b/qemu-timer.h
index 8cd8f83..345feea 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -12,6 +12,10 @@
 
 /* timers */
 
+#define SCALE_MS 1000000
+#define SCALE_US 1000
+#define SCALE_NS 1
+
 typedef struct QEMUClock QEMUClock;
 typedef void QEMUTimerCB(void *opaque);
 
@@ -54,6 +58,25 @@ void init_clocks(void);
 int init_timer_alarm(void);
 void quit_timers(void);
 
+static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
+                                           void *opaque)
+{
+    assert(clock != rt_clock);
+    return qemu_new_timer(clock, cb, opaque);
+}
+
+static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
+                                           void *opaque)
+{
+    assert(clock == rt_clock);
+    return qemu_new_timer(clock, cb, opaque);
+}
+
+static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
+{
+    return qemu_get_clock_ns(clock) / SCALE_MS;
+}
+
 static inline int64_t get_ticks_per_sec(void)
 {
     return 1000000000LL;
commit e0efb993b817564ef84e462ac1fe35f89b57ad7b
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Feb 23 19:09:16 2011 +0100

    Fix conversions from pointer to int and vice versa
    
    Here the int values fds[0], sigfd, s, sock and fd are converted
    to void pointers which are later converted back to an int value.
    
    These conversions should always use intptr_t instead of unsigned long.
    
    They are needed for environments where sizeof(long) != sizeof(void *).
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 077729c..b6e658d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -278,7 +278,7 @@ static void qemu_event_increment(void)
 
 static void qemu_event_read(void *opaque)
 {
-    int fd = (unsigned long)opaque;
+    int fd = (intptr_t)opaque;
     ssize_t len;
     char buffer[512];
 
@@ -306,7 +306,7 @@ static int qemu_event_init(void)
         goto fail;
     }
     qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
-                         (void *)(unsigned long)fds[0]);
+                         (void *)(intptr_t)fds[0]);
 
     io_thread_fd = fds[1];
     return 0;
@@ -327,7 +327,7 @@ static void dummy_signal(int sig)
  */
 static void sigfd_handler(void *opaque)
 {
-    int fd = (unsigned long) opaque;
+    int fd = (intptr_t)opaque;
     struct qemu_signalfd_siginfo info;
     struct sigaction action;
     ssize_t len;
@@ -395,7 +395,7 @@ static int qemu_signal_init(void)
     fcntl_setfl(sigfd, O_NONBLOCK);
 
     qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
-                         (void *)(unsigned long) sigfd);
+                         (void *)(intptr_t)sigfd);
 
     return 0;
 }
diff --git a/migration-tcp.c b/migration-tcp.c
index b55f419..e8dff9d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -139,7 +139,7 @@ static void tcp_accept_incoming_migration(void *opaque)
 {
     struct sockaddr_in addr;
     socklen_t addrlen = sizeof(addr);
-    int s = (unsigned long)opaque;
+    int s = (intptr_t)opaque;
     QEMUFile *f;
     int c;
 
@@ -194,7 +194,7 @@ int tcp_start_incoming_migration(const char *host_port)
         goto err;
 
     qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
-                         (void *)(unsigned long)s);
+                         (void *)(intptr_t)s);
 
     return 0;
 
diff --git a/migration-unix.c b/migration-unix.c
index 57232c0..8b967f2 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -147,7 +147,7 @@ static void unix_accept_incoming_migration(void *opaque)
 {
     struct sockaddr_un addr;
     socklen_t addrlen = sizeof(addr);
-    int s = (unsigned long)opaque;
+    int s = (intptr_t)opaque;
     QEMUFile *f;
     int c;
 
@@ -204,7 +204,7 @@ int unix_start_incoming_migration(const char *path)
     }
 
     qemu_set_fd_handler2(sock, NULL, unix_accept_incoming_migration, NULL,
-			 (void *)(unsigned long)sock);
+			 (void *)(intptr_t)sock);
 
     return 0;
 
diff --git a/qemu-char.c b/qemu-char.c
index bd4e944..cad35d7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1376,7 +1376,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
 static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
 {
-    int fd = (int)(long)chr->opaque;
+    int fd = (int)(intptr_t)chr->opaque;
     uint8_t b;
 
     switch(cmd) {
@@ -1422,7 +1422,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
         return NULL;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
-    chr->opaque = (void *)(long)fd;
+    chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
     return chr;
commit d81e54de5919f46d911e971804bb4b4d77a8a88a
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 19 08:43:22 2011 +0000

    petalogix_ml605_mmu: remove unused variable
    
    Remove a write-only variable, spotted by GCC 4.6.0:
    /src/qemu/hw/petalogix_ml605_mmu.c: In function 'petalogix_ml605_init':
    /src/qemu/hw/petalogix_ml605_mmu.c:153:11: error: variable 'serial' set but not used [-Werror=unused-but-set-variable]
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index ca0986a..8213902 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -150,7 +150,6 @@ petalogix_ml605_init(ram_addr_t ram_size,
     ram_addr_t phys_ram;
     ram_addr_t phys_flash;
     qemu_irq irq[32], *cpu_irq;
-    void *serial = NULL;
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -185,8 +184,8 @@ petalogix_ml605_init(ram_addr_t ram_size,
         irq[i] = qdev_get_gpio_in(dev, i);
     }
 
-    serial = serial_mm_init(UART16550_BASEADDR + 0x1000, 2, irq[5],
-                        115200, serial_hds[0], 1, 0);
+    serial_mm_init(UART16550_BASEADDR + 0x1000, 2, irq[5], 115200,
+                   serial_hds[0], 1, 0);
 
     /* 2 timers at irq 2 @ 100 Mhz.  */
     xilinx_timer_create(TIMER_BASEADDR, irq[2], 2, 100 * 1000000);
commit 44bc10d5bcb1957f76925b849488288f74f623b7
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Tue Mar 15 20:48:52 2011 +0000

    qemu-thread: delete unused functions
    
    qemu_mutex_timedlock() and qemu_cond_timedwait() are no longer used.
    
    Remove them and their helper timespec_add_ms().
    
    Reported-by: François Revol <revol at free.fr>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 87c1a9f..2bd02ef 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -61,30 +61,6 @@ int qemu_mutex_trylock(QemuMutex *mutex)
     return pthread_mutex_trylock(&mutex->lock);
 }
 
-static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
-{
-    ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
-    ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
-    if (ts->tv_nsec >= 1000000000) {
-        ts->tv_nsec -= 1000000000;
-        ts->tv_sec++;
-    }
-}
-
-int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
-{
-    int err;
-    struct timespec ts;
-
-    clock_gettime(CLOCK_REALTIME, &ts);
-    timespec_add_ms(&ts, msecs);
-
-    err = pthread_mutex_timedlock(&mutex->lock, &ts);
-    if (err && err != ETIMEDOUT)
-        error_exit(err, __func__);
-    return err;
-}
-
 void qemu_mutex_unlock(QemuMutex *mutex)
 {
     int err;
@@ -139,20 +115,6 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
         error_exit(err, __func__);
 }
 
-int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
-{
-    struct timespec ts;
-    int err;
-
-    clock_gettime(CLOCK_REALTIME, &ts);
-    timespec_add_ms(&ts, msecs);
-
-    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
-    if (err && err != ETIMEDOUT)
-        error_exit(err, __func__);
-    return err;
-}
-
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
                        void *arg)
diff --git a/qemu-thread.h b/qemu-thread.h
index acdb6b2..edc7ab6 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -15,7 +15,6 @@ void qemu_mutex_init(QemuMutex *mutex);
 void qemu_mutex_destroy(QemuMutex *mutex);
 void qemu_mutex_lock(QemuMutex *mutex);
 int qemu_mutex_trylock(QemuMutex *mutex);
-int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs);
 void qemu_mutex_unlock(QemuMutex *mutex);
 
 void qemu_cond_init(QemuCond *cond);
@@ -29,7 +28,6 @@ void qemu_cond_destroy(QemuCond *cond);
 void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
-int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs);
 
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
commit 1a290aea8dd25bd8a6d0edb945b120ea26fc05e0
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Mar 13 19:00:52 2011 +0100

    w32: Add missing functions qemu_mutex_destroy, qemu_cond_destroy
    
    These functions were missing in commit
    9257d46d55f1fe4e8209be9a6870e339ac3266fe.
    
    Both functions are needed for compilations with
    configuration --enable-vnc-thread.
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index 2edcb1a..2d2d5ab 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -33,6 +33,12 @@ void qemu_mutex_init(QemuMutex *mutex)
     InitializeCriticalSection(&mutex->lock);
 }
 
+void qemu_mutex_destroy(QemuMutex *mutex)
+{
+    assert(mutex->owner == 0);
+    DeleteCriticalSection(&mutex->lock);
+}
+
 void qemu_mutex_lock(QemuMutex *mutex)
 {
     EnterCriticalSection(&mutex->lock);
@@ -80,6 +86,21 @@ void qemu_cond_init(QemuCond *cond)
     }
 }
 
+void qemu_cond_destroy(QemuCond *cond)
+{
+    BOOL result;
+    result = CloseHandle(cond->continue_event);
+    if (!result) {
+        error_exit(GetLastError(), __func__);
+    }
+    cond->continue_event = 0;
+    result = CloseHandle(cond->sema);
+    if (!result) {
+        error_exit(GetLastError(), __func__);
+    }
+    cond->sema = 0;
+}
+
 void qemu_cond_signal(QemuCond *cond)
 {
     DWORD result;
commit ca22a3a3758ee7ab14166058d4ce36bc6cdfdfd8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Mar 6 16:09:49 2011 +0100

    i8254: Fix migration from older versions
    
    qdev conversion broke migration as the previous version used vmstate
    instance IDs derived from the iobase. Fix it by registering a legacy
    alias.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8254.c b/hw/i8254.c
index eaf5d3e..47c9d73 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -520,6 +520,8 @@ static int pit_initfn(ISADevice *dev)
     register_ioport_read(pit->iobase, 3, 1, pit_ioport_read, pit);
     isa_init_ioport(dev, pit->iobase);
 
+    qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
+
     return 0;
 }
 
commit dc7a09cfe47679d89289101cc9eb387c45e48fe7
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:31 2011 +0100

    Expose thread_id in info cpus
    
    Based on patch by Glauber Costa:
    
    To allow management applications like libvirt to apply CPU affinities to
    the VCPU threads, expose their ID via info cpus. This patch provides the
    pre-existing and used interface from qemu-kvm.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-defs.h b/cpu-defs.h
index 2b59fa6..db48a7a 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -203,6 +203,7 @@ typedef struct CPUWatchpoint {
     int nr_cores;  /* number of cores within this CPU package */        \
     int nr_threads;/* number of threads within this CPU */              \
     int running; /* Nonzero if cpu is currently running(usermode).  */  \
+    int thread_id;                                                      \
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
diff --git a/cpus.c b/cpus.c
index d310b7e..28c2da2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -776,6 +776,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
 
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(env->thread);
+    env->thread_id = qemu_get_thread_id();
 
     r = kvm_init_vcpu(env);
     if (r < 0) {
@@ -817,6 +818,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     /* signal CPU creation */
     qemu_mutex_lock(&qemu_global_mutex);
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        env->thread_id = qemu_get_thread_id();
         env->created = 1;
     }
     qemu_cond_signal(&qemu_cpu_cond);
diff --git a/exec.c b/exec.c
index c5358c3..964ce31 100644
--- a/exec.c
+++ b/exec.c
@@ -638,6 +638,9 @@ void cpu_exec_init(CPUState *env)
     env->numa_node = 0;
     QTAILQ_INIT(&env->breakpoints);
     QTAILQ_INIT(&env->watchpoints);
+#ifndef CONFIG_USER_ONLY
+    env->thread_id = qemu_get_thread_id();
+#endif
     *penv = env;
 #if defined(CONFIG_USER_ONLY)
     cpu_list_unlock();
diff --git a/monitor.c b/monitor.c
index ae20927..481572d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -897,6 +897,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
         monitor_printf(mon, " (halted)");
     }
 
+    monitor_printf(mon, " thread_id=%" PRId64 " ",
+                   qdict_get_int(cpu, "thread_id"));
+
     monitor_printf(mon, "\n");
 }
 
@@ -941,6 +944,7 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
 #elif defined(TARGET_MIPS)
         qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
 #endif
+        qdict_put(cpu, "thread_id", qint_from_int(env->thread_id));
 
         qlist_append(cpu_list, cpu);
     }
diff --git a/os-posix.c b/os-posix.c
index 38c29d1..7971f86 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -41,6 +41,7 @@
 
 #ifdef CONFIG_LINUX
 #include <sys/prctl.h>
+#include <sys/syscall.h>
 #endif
 
 #ifdef CONFIG_EVENTFD
@@ -382,3 +383,12 @@ int qemu_create_pidfile(const char *filename)
 
     return 0;
 }
+
+int qemu_get_thread_id(void)
+{
+#if defined (__linux__)
+    return syscall(SYS_gettid);
+#else
+    return getpid();
+#endif
+}
diff --git a/os-win32.c b/os-win32.c
index c971d92..d6d54c6 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -266,3 +266,8 @@ int qemu_create_pidfile(const char *filename)
     }
     return 0;
 }
+
+int qemu_get_thread_id(void)
+{
+    return GetCurrentThreadId();
+}
diff --git a/osdep.h b/osdep.h
index 27eedcf..748df54 100644
--- a/osdep.h
+++ b/osdep.h
@@ -130,5 +130,6 @@ void qemu_vfree(void *ptr);
 int qemu_madvise(void *addr, size_t len, int advice);
 
 int qemu_create_pidfile(const char *filename);
+int qemu_get_thread_id(void);
 
 #endif
diff --git a/qmp-commands.hx b/qmp-commands.hx
index df40a3d..1f72a8d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1194,6 +1194,7 @@ Return a json-array. Each CPU is represented by a json-object, which contains:
      "nip": PPC (json-int)
      "pc" and "npc": sparc (json-int)
      "PC": mips (json-int)
+- "thread_id": ID of the underlying host thread (json-int)
 
 Example:
 
@@ -1205,12 +1206,14 @@ Example:
             "current":true,
             "halted":false,
             "pc":3227107138
+            "thread_id":3134
          },
          {
             "CPU":1,
             "current":false,
             "halted":true,
             "pc":7108165
+            "thread_id":3135
          }
       ]
    }
commit f2574737f6a1218b4f4809ad6c8aba935126d90f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:30 2011 +0100

    kvm: x86: Push kvm_arch_debug to kvm_arch_handle_exit
    
    There are no generic bits remaining in the handling of KVM_EXIT_DEBUG.
    So push its logic completely into arch hands, i.e. only x86 so far.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index f34cb69..1d7e8ea 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -975,17 +975,6 @@ int kvm_cpu_exec(CPUState *env)
             ret = kvm_handle_internal_error(env, run);
             break;
 #endif
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-        case KVM_EXIT_DEBUG:
-            DPRINTF("kvm_exit_debug\n");
-            if (kvm_arch_debug(&run->debug.arch)) {
-                ret = EXCP_DEBUG;
-                break;
-            }
-            /* re-enter, this exception was guest-internal */
-            ret = 0;
-            break;
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
         default:
             DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(env, run);
diff --git a/kvm.h b/kvm.h
index 7bc04e0..d565dba 100644
--- a/kvm.h
+++ b/kvm.h
@@ -136,8 +136,6 @@ struct kvm_sw_breakpoint {
 
 QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
 
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
-
 struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
                                                  target_ulong pc);
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 3920444..a13599d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1731,31 +1731,31 @@ void kvm_arch_remove_all_hw_breakpoints(void)
 
 static CPUWatchpoint hw_watchpoint;
 
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+static int kvm_handle_debug(struct kvm_debug_exit_arch *arch_info)
 {
-    int handle = 0;
+    int ret = 0;
     int n;
 
     if (arch_info->exception == 1) {
         if (arch_info->dr6 & (1 << 14)) {
             if (cpu_single_env->singlestep_enabled) {
-                handle = 1;
+                ret = EXCP_DEBUG;
             }
         } else {
             for (n = 0; n < 4; n++) {
                 if (arch_info->dr6 & (1 << n)) {
                     switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
                     case 0x0:
-                        handle = 1;
+                        ret = EXCP_DEBUG;
                         break;
                     case 0x1:
-                        handle = 1;
+                        ret = EXCP_DEBUG;
                         cpu_single_env->watchpoint_hit = &hw_watchpoint;
                         hw_watchpoint.vaddr = hw_breakpoint[n].addr;
                         hw_watchpoint.flags = BP_MEM_WRITE;
                         break;
                     case 0x3:
-                        handle = 1;
+                        ret = EXCP_DEBUG;
                         cpu_single_env->watchpoint_hit = &hw_watchpoint;
                         hw_watchpoint.vaddr = hw_breakpoint[n].addr;
                         hw_watchpoint.flags = BP_MEM_ACCESS;
@@ -1765,17 +1765,18 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
             }
         }
     } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc)) {
-        handle = 1;
+        ret = EXCP_DEBUG;
     }
-    if (!handle) {
+    if (ret == 0) {
         cpu_synchronize_state(cpu_single_env);
         assert(cpu_single_env->exception_injected == -1);
 
+        /* pass to guest */
         cpu_single_env->exception_injected = arch_info->exception;
         cpu_single_env->has_error_code = 0;
     }
 
-    return handle;
+    return ret;
 }
 
 void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
@@ -1851,6 +1852,12 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                 run->ex.exception, run->ex.error_code);
         ret = -1;
         break;
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+    case KVM_EXIT_DEBUG:
+        DPRINTF("kvm_exit_debug\n");
+        ret = kvm_handle_debug(&run->debug.arch);
+        break;
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
commit 2a4dac835008da7328e61d8596b310c05cab801d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:29 2011 +0100

    kvm: x86: Reorder functions in kvm.c
    
    Required for next patch which will access guest debug services from
    kvm_arch_handle_exit. No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 6f84610..3920444 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1624,60 +1624,6 @@ static int kvm_handle_halt(CPUState *env)
     return 0;
 }
 
-static bool host_supports_vmx(void)
-{
-    uint32_t ecx, unused;
-
-    host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
-    return ecx & CPUID_EXT_VMX;
-}
-
-#define VMX_INVALID_GUEST_STATE 0x80000021
-
-int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
-{
-    uint64_t code;
-    int ret;
-
-    switch (run->exit_reason) {
-    case KVM_EXIT_HLT:
-        DPRINTF("handle_hlt\n");
-        ret = kvm_handle_halt(env);
-        break;
-    case KVM_EXIT_SET_TPR:
-        ret = 0;
-        break;
-    case KVM_EXIT_FAIL_ENTRY:
-        code = run->fail_entry.hardware_entry_failure_reason;
-        fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
-                code);
-        if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
-            fprintf(stderr,
-                    "\nIf you're runnning a guest on an Intel machine without "
-                        "unrestricted mode\n"
-                    "support, the failure can be most likely due to the guest "
-                        "entering an invalid\n"
-                    "state for Intel VT. For example, the guest maybe running "
-                        "in big real mode\n"
-                    "which is not supported on less recent Intel processors."
-                        "\n\n");
-        }
-        ret = -1;
-        break;
-    case KVM_EXIT_EXCEPTION:
-        fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
-                run->ex.exception, run->ex.error_code);
-        ret = -1;
-        break;
-    default:
-        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
-        ret = -1;
-        break;
-    }
-
-    return ret;
-}
-
 #ifdef KVM_CAP_SET_GUEST_DEBUG
 int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
 {
@@ -1860,6 +1806,60 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
 }
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
 
+static bool host_supports_vmx(void)
+{
+    uint32_t ecx, unused;
+
+    host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
+    return ecx & CPUID_EXT_VMX;
+}
+
+#define VMX_INVALID_GUEST_STATE 0x80000021
+
+int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
+{
+    uint64_t code;
+    int ret;
+
+    switch (run->exit_reason) {
+    case KVM_EXIT_HLT:
+        DPRINTF("handle_hlt\n");
+        ret = kvm_handle_halt(env);
+        break;
+    case KVM_EXIT_SET_TPR:
+        ret = 0;
+        break;
+    case KVM_EXIT_FAIL_ENTRY:
+        code = run->fail_entry.hardware_entry_failure_reason;
+        fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
+                code);
+        if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
+            fprintf(stderr,
+                    "\nIf you're runnning a guest on an Intel machine without "
+                        "unrestricted mode\n"
+                    "support, the failure can be most likely due to the guest "
+                        "entering an invalid\n"
+                    "state for Intel VT. For example, the guest maybe running "
+                        "in big real mode\n"
+                    "which is not supported on less recent Intel processors."
+                        "\n\n");
+        }
+        ret = -1;
+        break;
+    case KVM_EXIT_EXCEPTION:
+        fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
+                run->ex.exception, run->ex.error_code);
+        ret = -1;
+        break;
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return !(env->cr[0] & CR0_PE_MASK) ||
commit bb4ea39329d6c3de4c10034621781f703d095699
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:28 2011 +0100

    kvm: Align kvm_arch_handle_exit to kvm_cpu_exec changes
    
    Make the return code of kvm_arch_handle_exit directly usable for
    kvm_cpu_exec. This is straightforward for x86 and ppc, just s390
    would require more work. Avoid this for now by pushing the return code
    translation logic into s390's kvm_arch_handle_exit.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Alexander Graf <agraf at suse.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 271e361..f34cb69 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -989,11 +989,6 @@ int kvm_cpu_exec(CPUState *env)
         default:
             DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(env, run);
-            if (ret == 0) {
-                ret = EXCP_INTERRUPT;
-            } else if (ret > 0) {
-                ret = 0;
-            }
             break;
         }
     } while (ret == 0);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 032bc3e..6f84610 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1618,10 +1618,10 @@ static int kvm_handle_halt(CPUState *env)
           (env->eflags & IF_MASK)) &&
         !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
         env->halted = 1;
-        return 0;
+        return EXCP_HLT;
     }
 
-    return 1;
+    return 0;
 }
 
 static bool host_supports_vmx(void)
@@ -1637,7 +1637,7 @@ static bool host_supports_vmx(void)
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 {
     uint64_t code;
-    int ret = 0;
+    int ret;
 
     switch (run->exit_reason) {
     case KVM_EXIT_HLT:
@@ -1645,7 +1645,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         ret = kvm_handle_halt(env);
         break;
     case KVM_EXIT_SET_TPR:
-        ret = 1;
+        ret = 0;
         break;
     case KVM_EXIT_FAIL_ENTRY:
         code = run->fail_entry.hardware_entry_failure_reason;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 6c99a16..593eb98 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -271,7 +271,7 @@ static int kvmppc_handle_halt(CPUState *env)
         env->exception_index = EXCP_HLT;
     }
 
-    return 1;
+    return 0;
 }
 
 /* map dcr access to existing qemu dcr emulation */
@@ -280,7 +280,7 @@ static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
     if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
         fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
 
-    return 1;
+    return 0;
 }
 
 static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
@@ -288,12 +288,12 @@ static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
     if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
         fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
 
-    return 1;
+    return 0;
 }
 
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 {
-    int ret = 0;
+    int ret;
 
     switch (run->exit_reason) {
     case KVM_EXIT_DCR:
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a85ae0f..9123203 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -497,6 +497,11 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
             break;
     }
 
+    if (ret == 0) {
+        ret = EXCP_INTERRUPT;
+    } else if (ret > 0) {
+        ret = 0;
+    }
     return ret;
 }
 
commit d73cd8f4ea1c2944bd16f7a1c445eaa25c9e6e26
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:27 2011 +0100

    kvm: Rework inner loop of kvm_cpu_exec
    
    Let kvm_cpu_exec return EXCP_* values consistently and generate those
    codes already inside its inner loop. This means we will now re-enter the
    kernel while ret == 0.
    
    Update kvm_handle_internal_error accordingly, but keep
    kvm_arch_handle_exit untouched, it will be converted in a separate step.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 8531555..271e361 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -831,7 +831,7 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
             cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-            return 0;
+            return EXCP_INTERRUPT;
         }
     }
     /* FIXME: Should trigger a qmp message to let management know
@@ -931,14 +931,13 @@ int kvm_cpu_exec(CPUState *env)
         if (run_ret < 0) {
             if (run_ret == -EINTR || run_ret == -EAGAIN) {
                 DPRINTF("io window exit\n");
-                ret = 0;
+                ret = EXCP_INTERRUPT;
                 break;
             }
             DPRINTF("kvm run failed %s\n", strerror(-run_ret));
             abort();
         }
 
-        ret = 0; /* exit loop */
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
             DPRINTF("handle_io\n");
@@ -947,7 +946,7 @@ int kvm_cpu_exec(CPUState *env)
                           run->io.direction,
                           run->io.size,
                           run->io.count);
-            ret = 1;
+            ret = 0;
             break;
         case KVM_EXIT_MMIO:
             DPRINTF("handle_mmio\n");
@@ -955,14 +954,16 @@ int kvm_cpu_exec(CPUState *env)
                                    run->mmio.data,
                                    run->mmio.len,
                                    run->mmio.is_write);
-            ret = 1;
+            ret = 0;
             break;
         case KVM_EXIT_IRQ_WINDOW_OPEN:
             DPRINTF("irq_window_open\n");
+            ret = EXCP_INTERRUPT;
             break;
         case KVM_EXIT_SHUTDOWN:
             DPRINTF("shutdown\n");
             qemu_system_reset_request();
+            ret = EXCP_INTERRUPT;
             break;
         case KVM_EXIT_UNKNOWN:
             fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
@@ -979,28 +980,29 @@ int kvm_cpu_exec(CPUState *env)
             DPRINTF("kvm_exit_debug\n");
             if (kvm_arch_debug(&run->debug.arch)) {
                 ret = EXCP_DEBUG;
-                goto out;
+                break;
             }
             /* re-enter, this exception was guest-internal */
-            ret = 1;
+            ret = 0;
             break;
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
         default:
             DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(env, run);
+            if (ret == 0) {
+                ret = EXCP_INTERRUPT;
+            } else if (ret > 0) {
+                ret = 0;
+            }
             break;
         }
-    } while (ret > 0);
+    } while (ret == 0);
 
     if (ret < 0) {
         cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
         vm_stop(VMSTOP_PANIC);
     }
-    ret = EXCP_INTERRUPT;
 
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-out:
-#endif
     env->exit_request = 0;
     cpu_single_env = NULL;
     return ret;
commit dc77d341d2dcd3eeadae736ed7e7775e22324844
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:26 2011 +0100

    kvm: Reorder error handling of KVM_RUN
    
    Test for general errors first as this is the slower path.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index be235ec..8531555 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -928,13 +928,12 @@ int kvm_cpu_exec(CPUState *env)
 
         kvm_flush_coalesced_mmio_buffer();
 
-        if (run_ret == -EINTR || run_ret == -EAGAIN) {
-            DPRINTF("io window exit\n");
-            ret = 0;
-            break;
-        }
-
         if (run_ret < 0) {
+            if (run_ret == -EINTR || run_ret == -EAGAIN) {
+                DPRINTF("io window exit\n");
+                ret = 0;
+                break;
+            }
             DPRINTF("kvm run failed %s\n", strerror(-run_ret));
             abort();
         }
commit 7cbb533f92f040ab1dbafe2233a51c7d4e321d90
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:25 2011 +0100

    kvm: Keep KVM_RUN return value in separate variable
    
    Avoid using 'ret' both for the return value of KVM_RUN as well as the
    code kvm_cpu_exec is supposed to return. Both have no direct relation.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 906521e..be235ec 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -890,7 +890,7 @@ void kvm_cpu_synchronize_post_init(CPUState *env)
 int kvm_cpu_exec(CPUState *env)
 {
     struct kvm_run *run = env->kvm_run;
-    int ret;
+    int ret, run_ret;
 
     DPRINTF("kvm_cpu_exec()\n");
 
@@ -920,7 +920,7 @@ int kvm_cpu_exec(CPUState *env)
         cpu_single_env = NULL;
         qemu_mutex_unlock_iothread();
 
-        ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
+        run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
 
         qemu_mutex_lock_iothread();
         cpu_single_env = env;
@@ -928,14 +928,14 @@ int kvm_cpu_exec(CPUState *env)
 
         kvm_flush_coalesced_mmio_buffer();
 
-        if (ret == -EINTR || ret == -EAGAIN) {
+        if (run_ret == -EINTR || run_ret == -EAGAIN) {
             DPRINTF("io window exit\n");
             ret = 0;
             break;
         }
 
-        if (ret < 0) {
-            DPRINTF("kvm run failed %s\n", strerror(-ret));
+        if (run_ret < 0) {
+            DPRINTF("kvm run failed %s\n", strerror(-run_ret));
             abort();
         }
 
commit 51e8fa606e3cbef9cdf5c84f2468dcf1e07ddb70
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:24 2011 +0100

    kvm: Consider EXIT_DEBUG unknown without CAP_SET_GUEST_DEBUG
    
    Without KVM_CAP_SET_GUEST_DEBUG, we neither motivate the kernel to
    report KVM_EXIT_DEBUG nor do we expect such exits. So fall through to
    the arch code which will simply report an unknown exit reason.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 62b0984..906521e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -975,17 +975,17 @@ int kvm_cpu_exec(CPUState *env)
             ret = kvm_handle_internal_error(env, run);
             break;
 #endif
+#ifdef KVM_CAP_SET_GUEST_DEBUG
         case KVM_EXIT_DEBUG:
             DPRINTF("kvm_exit_debug\n");
-#ifdef KVM_CAP_SET_GUEST_DEBUG
             if (kvm_arch_debug(&run->debug.arch)) {
                 ret = EXCP_DEBUG;
                 goto out;
             }
             /* re-enter, this exception was guest-internal */
             ret = 1;
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
             break;
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
         default:
             DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(env, run);
commit 0c03266a965a8e5353bb0e8d1b2d3a3ac04aa686
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:23 2011 +0100

    kvm: x86: Synchronize PAT MSR with the kernel
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 3a07fce..032bc3e 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -861,6 +861,7 @@ static int kvm_put_msrs(CPUState *env, int level)
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
+    kvm_msr_entry_set(&msrs[n++], MSR_PAT, env->pat);
     if (has_msr_star) {
         kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
     }
@@ -1113,6 +1114,7 @@ static int kvm_get_msrs(CPUState *env)
     msrs[n++].index = MSR_IA32_SYSENTER_CS;
     msrs[n++].index = MSR_IA32_SYSENTER_ESP;
     msrs[n++].index = MSR_IA32_SYSENTER_EIP;
+    msrs[n++].index = MSR_PAT;
     if (has_msr_star) {
         msrs[n++].index = MSR_STAR;
     }
@@ -1168,6 +1170,9 @@ static int kvm_get_msrs(CPUState *env)
         case MSR_IA32_SYSENTER_EIP:
             env->sysenter_eip = msrs[i].data;
             break;
+        case MSR_PAT:
+            env->pat = msrs[i].data;
+            break;
         case MSR_STAR:
             env->star = msrs[i].data;
             break;
commit c995b495b9d6e60ab1e390bd398a22425d0b3c8c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:22 2011 +0100

    x86: Save/restore PAT MSR
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/machine.c b/target-i386/machine.c
index d78eceb..6384f54 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -491,6 +491,8 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(xcr0, CPUState, 12),
         VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
         VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
+
+        VMSTATE_UINT64_V(pat, CPUState, 13),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
commit ebda377f8c6d9a5ec69a0aeb2000aa5ce74f7fa2
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:21 2011 +0100

    x86: Properly reset PAT MSR
    
    Conforming to the Intel spec, set the power-on value of PAT also on
    reset, but save it across INIT.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index d0eae75..c7047d5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -685,8 +685,6 @@ typedef struct CPUX86State {
 
     uint64_t tsc;
 
-    uint64_t pat;
-
     uint64_t mcg_status;
 
     /* exception/interrupt handling */
@@ -707,6 +705,8 @@ typedef struct CPUX86State {
 
     CPU_COMMON
 
+    uint64_t pat;
+
     /* processor features (e.g. for CPUID insn) */
     uint32_t cpuid_level;
     uint32_t cpuid_vendor1;
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 5382a28..814d13e 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -847,7 +847,6 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
     env->cpuid_version |= def->stepping;
     env->cpuid_features = def->features;
-    env->pat = 0x0007040600070406ULL;
     env->cpuid_ext_features = def->ext_features;
     env->cpuid_ext2_features = def->ext2_features;
     env->cpuid_ext3_features = def->ext3_features;
diff --git a/target-i386/helper.c b/target-i386/helper.c
index a08309f..d15fca5 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -99,6 +99,8 @@ void cpu_reset(CPUX86State *env)
 
     env->mxcsr = 0x1f80;
 
+    env->pat = 0x0007040600070406ULL;
+
     memset(env->dr, 0, sizeof(env->dr));
     env->dr[6] = DR6_FIXED_1;
     env->dr[7] = DR7_FIXED_1;
@@ -1280,8 +1282,11 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
 void do_cpu_init(CPUState *env)
 {
     int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
+    uint64_t pat = env->pat;
+
     cpu_reset(env);
     env->interrupt_request = sipi;
+    env->pat = pat;
     apic_init_reset(env->apic_state);
     env->halted = !cpu_is_bsp(env);
 }
commit d841b6c4f16c3fc7afe2ce355e7e42813345f053
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:20 2011 +0100

    kvm: Mark VCPU state dirty on creation
    
    This avoids that early cpu_synchronize_state calls try to retrieve an
    uninitialized state from the kernel. That even causes a deadlock if
    io-thread is enabled.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 226843c..62b0984 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -211,6 +211,7 @@ int kvm_init_vcpu(CPUState *env)
 
     env->kvm_fd = ret;
     env->kvm_state = s;
+    env->kvm_vcpu_dirty = 1;
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
     if (mmap_size < 0) {
commit 4601f7b04c63072c73870d4f4db2a5c5ad5ad8d2
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:19 2011 +0100

    kvm: x86: Do not leave halt if interrupts are disabled
    
    When an external interrupt is pending but IF is cleared, we must not
    leave the halt state prematurely.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f7995bd..3a07fce 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1590,7 +1590,9 @@ int kvm_arch_process_async_events(CPUState *env)
         return 0;
     }
 
-    if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+    if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+         (env->eflags & IF_MASK)) ||
+        (env->interrupt_request & CPU_INTERRUPT_NMI)) {
         env->halted = 0;
     }
     if (env->interrupt_request & CPU_INTERRUPT_INIT) {
commit f2c1cc81c8229e8c1e26aae517d32aa534936a0c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:18 2011 +0100

    kvm: Add in-kernel irqchip awareness to cpu_thread_is_idle
    
    With in-kernel irqchip support enabled, the vcpu threads sleep in kernel
    space while halted. Account for this difference in cpu_thread_is_idle.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 975a6ce..d310b7e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -148,7 +148,8 @@ static bool cpu_thread_is_idle(CPUState *env)
     if (env->stopped || !vm_running) {
         return true;
     }
-    if (!env->halted || qemu_cpu_has_work(env)) {
+    if (!env->halted || qemu_cpu_has_work(env) ||
+        (kvm_enabled() && kvm_irqchip_in_kernel())) {
         return false;
     }
     return true;
commit 00914b7d9707586d2ebe9faeea6f733c9fd51dc8
Author: Michal Simek <monstr at monstr.eu>
Date:   Mon Mar 14 11:29:19 2011 +0100

    microblaze: Add PetaLogix ml605 MMU little-endian ref design
    
    Add the first Microblaze little endian platform.
    Platform uses uart16550, axi ethernet, timer, intc.
    
    Signed-off-by: Michal Simek <monstr at monstr.eu>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/Makefile b/Makefile
index eca4c76..89e88b4 100644
--- a/Makefile
+++ b/Makefile
@@ -211,7 +211,7 @@ gpxe-eepro100-80861209.rom \
 pxe-e1000.bin \
 pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
-bamboo.dtb petalogix-s3adsp1800.dtb \
+bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin \
 s390-zipl.rom
 else
diff --git a/Makefile.target b/Makefile.target
index d11eb4f..62b102a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -266,6 +266,7 @@ obj-mips-y += cirrus_vga.o
 obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
+obj-microblaze-y += petalogix_ml605_mmu.o
 
 obj-microblaze-y += microblaze_pic_cpu.o
 obj-microblaze-y += xilinx_intc.o
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
new file mode 100644
index 0000000..ca0986a
--- /dev/null
+++ b/hw/petalogix_ml605_mmu.c
@@ -0,0 +1,267 @@
+/*
+ * Model of Petalogix linux reference design targeting Xilinx Spartan ml605
+ * board.
+ *
+ * Copyright (c) 2011 Michal Simek <monstr at monstr.eu>
+ * Copyright (c) 2011 PetaLogix
+ * Copyright (c) 2009 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+#include "net.h"
+#include "flash.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "device_tree.h"
+#include "xilinx.h"
+#include "loader.h"
+#include "elf.h"
+#include "blockdev.h"
+#include "pc.h"
+
+#include "xilinx_axidma.h"
+
+#define LMB_BRAM_SIZE  (128 * 1024)
+#define FLASH_SIZE     (32 * 1024 * 1024)
+
+static struct
+{
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+    env->regs[5] = boot_info.cmdline;
+    env->regs[7] = boot_info.fdt;
+    env->sregs[SR_PC] = boot_info.bootstrap_pc;
+    env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
+    /* setup pvr to match kernel setting */
+    env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
+    env->pvr.regs[0] |= PVR0_USE_FPU_MASK | PVR0_ENDI;
+    env->pvr.regs[0] = (env->pvr.regs[0] & ~PVR0_VERSION_MASK) | (0x14 << 8);
+    env->pvr.regs[2] ^= PVR2_USE_FPU2_MASK;
+    env->pvr.regs[4] = 0xc56b8000;
+    env->pvr.regs[5] = 0xc56be000;
+}
+
+#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
+static int petalogix_load_device_tree(target_phys_addr_t addr,
+                                      uint32_t ramsize,
+                                      target_phys_addr_t initrd_base,
+                                      target_phys_addr_t initrd_size,
+                                      const char *kernel_cmdline)
+{
+    char *path;
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt;
+    int r;
+
+    /* Try the local "mb.dtb" override.  */
+    fdt = load_device_tree("mb.dtb", &fdt_size);
+    if (!fdt) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+        if (path) {
+            fdt = load_device_tree(path, &fdt_size);
+            qemu_free(path);
+        }
+        if (!fdt) {
+            return 0;
+        }
+    }
+
+    r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
+    if (r < 0) {
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+    }
+    cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
+#else
+    /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
+       to the kernel.  */
+    fdt_size = load_image_targphys("mb.dtb", addr, 0x10000);
+    if (fdt_size < 0) {
+        path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+        if (path) {
+            fdt_size = load_image_targphys(path, addr, 0x10000);
+            qemu_free(path);
+        }
+    }
+
+    if (kernel_cmdline) {
+        fprintf(stderr,
+                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    }
+#endif
+    return fdt_size;
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x30000000LL;
+}
+
+#define MEMORY_BASEADDR 0x50000000
+#define FLASH_BASEADDR 0x86000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UART16550_BASEADDR 0x83e00000
+#define AXIENET_BASEADDR 0x82780000
+#define AXIDMA_BASEADDR 0x84600000
+
+static void
+petalogix_ml605_init(ram_addr_t ram_size,
+                          const char *boot_device,
+                          const char *kernel_filename,
+                          const char *kernel_cmdline,
+                          const char *initrd_filename, const char *cpu_model)
+{
+    DeviceState *dev;
+    CPUState *env;
+    int kernel_size;
+    DriveInfo *dinfo;
+    int i;
+    target_phys_addr_t ddr_base = MEMORY_BASEADDR;
+    ram_addr_t phys_lmb_bram;
+    ram_addr_t phys_ram;
+    ram_addr_t phys_flash;
+    qemu_irq irq[32], *cpu_irq;
+    void *serial = NULL;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "microblaze";
+    }
+    env = cpu_init(cpu_model);
+
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* Attach emulated BRAM through the LMB.  */
+    phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_ml605.lmb_bram",
+                                   LMB_BRAM_SIZE);
+    cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE,
+                                 phys_lmb_bram | IO_MEM_RAM);
+
+    phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size);
+    cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
+
+    phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* 5th parameter 2 means bank-width
+     * 10th paremeter 0 means little-endian */
+    pflash_cfi01_register(FLASH_BASEADDR, phys_flash,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          2, 0x89, 0x18, 0x0000, 0x0, 0);
+
+
+    cpu_irq = microblaze_pic_init_cpu(env);
+    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    serial = serial_mm_init(UART16550_BASEADDR + 0x1000, 2, irq[5],
+                        115200, serial_hds[0], 1, 0);
+
+    /* 2 timers at irq 2 @ 100 Mhz.  */
+    xilinx_timer_create(TIMER_BASEADDR, irq[2], 2, 100 * 1000000);
+
+    /* axi ethernet and dma initialization. TODO: Dynamically connect them.  */
+    {
+        static struct XilinxDMAConnection dmach;
+
+        xilinx_axiethernet_create(&dmach, &nd_table[0], 0x82780000,
+                                  irq[3], 0x1000, 0x1000);
+        xilinx_axiethernetdma_create(&dmach, 0x84600000,
+                                     irq[1], irq[0], 100 * 1000000);
+    }
+
+    if (kernel_filename) {
+        uint64_t entry, low, high;
+        uint32_t base32;
+        int big_endian = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+        big_endian = 1;
+#endif
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high,
+                               big_endian, ELF_MACHINE, 0);
+        base32 = entry;
+        if (base32 == 0xc0000000) {
+            kernel_size = load_elf(kernel_filename, translate_kernel_address,
+                                   NULL, &entry, NULL, NULL,
+                                   big_endian, ELF_MACHINE, 0);
+        }
+        /* Always boot into physical ram.  */
+        boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+
+        /* If it wasn't an ELF image, try an u-boot image.  */
+        if (kernel_size < 0) {
+            target_phys_addr_t uentry, loadaddr;
+
+            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+            boot_info.bootstrap_pc = uentry;
+            high = (loadaddr + kernel_size + 3) & ~3;
+        }
+
+        /* Not an ELF image nor an u-boot image, try a RAW image.  */
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ddr_base,
+                                              ram_size);
+            boot_info.bootstrap_pc = ddr_base;
+            high = (ddr_base + kernel_size + 3) & ~3;
+        }
+
+        boot_info.cmdline = high + 4096;
+        if (kernel_cmdline && strlen(kernel_cmdline)) {
+            pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
+        }
+        /* Provide a device-tree.  */
+        boot_info.fdt = boot_info.cmdline + 4096;
+        petalogix_load_device_tree(boot_info.fdt, ram_size,
+                                   0, 0,
+                                   kernel_cmdline);
+    }
+}
+
+static QEMUMachine petalogix_ml605_machine = {
+    .name = "petalogix-ml605",
+    .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
+    .init = petalogix_ml605_init,
+    .is_default = 0
+};
+
+static void petalogix_ml605_machine_init(void)
+{
+    qemu_register_machine(&petalogix_ml605_machine);
+}
+
+machine_init(petalogix_ml605_machine_init);
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 705ff5b..090e6f7 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -48,3 +48,42 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
     return dev;
 }
+
+static inline DeviceState *
+xilinx_axiethernet_create(void *dmach,
+                          NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
+                          int txmem, int rxmem)
+{
+    DeviceState *dev;
+    qemu_check_nic_model(nd, "xilinx-axienet");
+
+    dev = qdev_create(NULL, "xilinx,axienet");
+    qdev_set_nic_properties(dev, nd);
+    qdev_prop_set_uint32(dev, "c_rxmem", rxmem);
+    qdev_prop_set_uint32(dev, "c_txmem", txmem);
+    qdev_prop_set_ptr(dev, "dmach", dmach);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
+}
+
+static inline DeviceState *
+xilinx_axiethernetdma_create(void *dmach,
+                             target_phys_addr_t base, qemu_irq irq,
+                             qemu_irq irq2, int freqhz)
+{
+    DeviceState *dev = NULL;
+
+    dev = qdev_create(NULL, "xilinx,axidma");
+    qdev_prop_set_uint32(dev, "freqhz", freqhz);
+    qdev_prop_set_ptr(dev, "dmach", dmach);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq2);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq);
+
+    return dev;
+}
diff --git a/pc-bios/petalogix-ml605.dtb b/pc-bios/petalogix-ml605.dtb
new file mode 100644
index 0000000..fbbd45f
Binary files /dev/null and b/pc-bios/petalogix-ml605.dtb differ
commit 93f1e4016b5e09a55d6f67fdfab37f80feb0ac29
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date:   Mon Mar 14 11:13:55 2011 +0100

    xilinx: Add AXIENET & DMA models
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/Makefile.target b/Makefile.target
index f0df98e..d11eb4f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -272,6 +272,8 @@ obj-microblaze-y += xilinx_intc.o
 obj-microblaze-y += xilinx_timer.o
 obj-microblaze-y += xilinx_uartlite.o
 obj-microblaze-y += xilinx_ethlite.o
+obj-microblaze-y += xilinx_axidma.o
+obj-microblaze-y += xilinx_axienet.o
 
 obj-microblaze-$(CONFIG_FDT) += device_tree.o
 
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
new file mode 100644
index 0000000..e32534f
--- /dev/null
+++ b/hw/xilinx_axidma.c
@@ -0,0 +1,509 @@
+/*
+ * QEMU model of Xilinx AXI-DMA block.
+ *
+ * Copyright (c) 2011 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-timer.h"
+#include "qemu-log.h"
+#include "qdev-addr.h"
+
+#include "xilinx_axidma.h"
+
+#define D(x)
+
+#define R_DMACR             (0x00 / 4)
+#define R_DMASR             (0x04 / 4)
+#define R_CURDESC           (0x08 / 4)
+#define R_TAILDESC          (0x10 / 4)
+#define R_MAX               (0x30 / 4)
+
+enum {
+    DMACR_RUNSTOP = 1,
+    DMACR_TAILPTR_MODE = 2,
+    DMACR_RESET = 4
+};
+
+enum {
+    DMASR_HALTED = 1,
+    DMASR_IDLE  = 2,
+    DMASR_IOC_IRQ  = 1 << 12,
+    DMASR_DLY_IRQ  = 1 << 13,
+
+    DMASR_IRQ_MASK = 7 << 12
+};
+
+struct SDesc {
+    uint64_t nxtdesc;
+    uint64_t buffer_address;
+    uint64_t reserved;
+    uint32_t control;
+    uint32_t status;
+    uint32_t app[6];
+};
+
+enum {
+    SDESC_CTRL_EOF = (1 << 26),
+    SDESC_CTRL_SOF = (1 << 27),
+
+    SDESC_CTRL_LEN_MASK = (1 << 23) - 1
+};
+
+enum {
+    SDESC_STATUS_EOF = (1 << 26),
+    SDESC_STATUS_SOF_BIT = 27,
+    SDESC_STATUS_SOF = (1 << SDESC_STATUS_SOF_BIT),
+    SDESC_STATUS_COMPLETE = (1 << 31)
+};
+
+struct AXIStream {
+    QEMUBH *bh;
+    ptimer_state *ptimer;
+    qemu_irq irq;
+
+    int nr;
+
+    struct SDesc desc;
+    int pos;
+    unsigned int complete_cnt;
+    uint32_t regs[R_MAX];
+};
+
+struct XilinxAXIDMA {
+    SysBusDevice busdev;
+    uint32_t freqhz;
+    void *dmach;
+
+    struct AXIStream streams[2];
+};
+
+/*
+ * Helper calls to extract info from desriptors and other trivial
+ * state from regs.
+ */
+static inline int stream_desc_sof(struct SDesc *d)
+{
+    return d->control & SDESC_CTRL_SOF;
+}
+
+static inline int stream_desc_eof(struct SDesc *d)
+{
+    return d->control & SDESC_CTRL_EOF;
+}
+
+static inline int stream_resetting(struct AXIStream *s)
+{
+    return !!(s->regs[R_DMACR] & DMACR_RESET);
+}
+
+static inline int stream_running(struct AXIStream *s)
+{
+    return s->regs[R_DMACR] & DMACR_RUNSTOP;
+}
+
+static inline int stream_halted(struct AXIStream *s)
+{
+    return s->regs[R_DMASR] & DMASR_HALTED;
+}
+
+static inline int stream_idle(struct AXIStream *s)
+{
+    return !!(s->regs[R_DMASR] & DMASR_IDLE);
+}
+
+static void stream_reset(struct AXIStream *s)
+{
+    s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
+    s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshhold.  */
+}
+
+/* Mapp an offset addr into a channel index.  */
+static inline int streamid_from_addr(target_phys_addr_t addr)
+{
+    int sid;
+
+    sid = addr / (0x30);
+    sid &= 1;
+    return sid;
+}
+
+#ifdef DEBUG_ENET
+static void stream_desc_show(struct SDesc *d)
+{
+    qemu_log("buffer_addr  = " PRIx64 "\n", d->buffer_address);
+    qemu_log("nxtdesc      = " PRIx64 "\n", d->nxtdesc);
+    qemu_log("control      = %x\n", d->control);
+    qemu_log("status       = %x\n", d->status);
+}
+#endif
+
+static void stream_desc_load(struct AXIStream *s, target_phys_addr_t addr)
+{
+    struct SDesc *d = &s->desc;
+    int i;
+
+    cpu_physical_memory_read(addr, (void *) d, sizeof *d);
+
+    /* Convert from LE into host endianness.  */
+    d->buffer_address = le64_to_cpu(d->buffer_address);
+    d->nxtdesc = le64_to_cpu(d->nxtdesc);
+    d->control = le32_to_cpu(d->control);
+    d->status = le32_to_cpu(d->status);
+    for (i = 0; i < ARRAY_SIZE(d->app); i++) {
+        d->app[i] = le32_to_cpu(d->app[i]);
+    }
+}
+
+static void stream_desc_store(struct AXIStream *s, target_phys_addr_t addr)
+{
+    struct SDesc *d = &s->desc;
+    int i;
+
+    /* Convert from host endianness into LE.  */
+    d->buffer_address = cpu_to_le64(d->buffer_address);
+    d->nxtdesc = cpu_to_le64(d->nxtdesc);
+    d->control = cpu_to_le32(d->control);
+    d->status = cpu_to_le32(d->status);
+    for (i = 0; i < ARRAY_SIZE(d->app); i++) {
+        d->app[i] = cpu_to_le32(d->app[i]);
+    }
+    cpu_physical_memory_write(addr, (void *) d, sizeof *d);
+}
+
+static void stream_update_irq(struct AXIStream *s)
+{
+    unsigned int pending, mask, irq;
+
+    pending = s->regs[R_DMASR] & DMASR_IRQ_MASK;
+    mask = s->regs[R_DMACR] & DMASR_IRQ_MASK;
+
+    irq = pending & mask;
+
+    qemu_set_irq(s->irq, !!irq);
+}
+
+static void stream_reload_complete_cnt(struct AXIStream *s)
+{
+    unsigned int comp_th;
+    comp_th = (s->regs[R_DMACR] >> 16) & 0xff;
+    s->complete_cnt = comp_th;
+}
+
+static void timer_hit(void *opaque)
+{
+    struct AXIStream *s = opaque;
+
+    stream_reload_complete_cnt(s);
+    s->regs[R_DMASR] |= DMASR_DLY_IRQ;
+    stream_update_irq(s);
+}
+
+static void stream_complete(struct AXIStream *s)
+{
+    unsigned int comp_delay;
+
+    /* Start the delayed timer.  */
+    comp_delay = s->regs[R_DMACR] >> 24;
+    if (comp_delay) {
+        ptimer_stop(s->ptimer);
+        ptimer_set_count(s->ptimer, comp_delay);
+        ptimer_run(s->ptimer, 1);
+    }
+
+    s->complete_cnt--;
+    if (s->complete_cnt == 0) {
+        /* Raise the IOC irq.  */
+        s->regs[R_DMASR] |= DMASR_IOC_IRQ;
+        stream_reload_complete_cnt(s);
+    }
+}
+
+static void stream_process_mem2s(struct AXIStream *s,
+                                 struct XilinxDMAConnection *dmach)
+{
+    uint32_t prev_d;
+    unsigned char txbuf[16 * 1024];
+    unsigned int txlen;
+    uint32_t app[6];
+
+    if (!stream_running(s) || stream_idle(s)) {
+        return;
+    }
+
+    while (1) {
+        stream_desc_load(s, s->regs[R_CURDESC]);
+
+        if (s->desc.status & SDESC_STATUS_COMPLETE) {
+            s->regs[R_DMASR] |= DMASR_IDLE;
+            break;
+        }
+
+        if (stream_desc_sof(&s->desc)) {
+            s->pos = 0;
+            memcpy(app, s->desc.app, sizeof app);
+        }
+
+        txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
+        if ((txlen + s->pos) > sizeof txbuf) {
+            hw_error("%s: too small internal txbuf! %d\n", __func__,
+                     txlen + s->pos);
+        }
+
+        cpu_physical_memory_read(s->desc.buffer_address,
+                                 txbuf + s->pos, txlen);
+        s->pos += txlen;
+
+        if (stream_desc_eof(&s->desc)) {
+            xlx_dma_push_to_client(dmach, txbuf, s->pos, app);
+            s->pos = 0;
+            stream_complete(s);
+        }
+
+        /* Update the descriptor.  */
+        s->desc.status = txlen | SDESC_STATUS_COMPLETE;
+        stream_desc_store(s, s->regs[R_CURDESC]);
+
+        /* Advance.  */
+        prev_d = s->regs[R_CURDESC];
+        s->regs[R_CURDESC] = s->desc.nxtdesc;
+        if (prev_d == s->regs[R_TAILDESC]) {
+            s->regs[R_DMASR] |= DMASR_IDLE;
+            break;
+        }
+    }
+}
+
+static void stream_process_s2mem(struct AXIStream *s,
+                                 unsigned char *buf, size_t len, uint32_t *app)
+{
+    uint32_t prev_d;
+    unsigned int rxlen;
+    int pos = 0;
+    int sof = 1;
+
+    if (!stream_running(s) || stream_idle(s)) {
+        return;
+    }
+
+    while (len) {
+        stream_desc_load(s, s->regs[R_CURDESC]);
+
+        if (s->desc.status & SDESC_STATUS_COMPLETE) {
+            s->regs[R_DMASR] |= DMASR_IDLE;
+            break;
+        }
+
+        rxlen = s->desc.control & SDESC_CTRL_LEN_MASK;
+        if (rxlen > len) {
+            /* It fits.  */
+            rxlen = len;
+        }
+
+        cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
+        len -= rxlen;
+        pos += rxlen;
+
+        /* Update the descriptor.  */
+        if (!len) {
+            int i;
+
+            stream_complete(s);
+            for (i = 0; i < 5; i++) {
+                s->desc.app[i] = app[i];
+            }
+            s->desc.status |= SDESC_STATUS_EOF;
+        }
+
+        s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
+        s->desc.status |= SDESC_STATUS_COMPLETE;
+        stream_desc_store(s, s->regs[R_CURDESC]);
+        sof = 0;
+
+        /* Advance.  */
+        prev_d = s->regs[R_CURDESC];
+        s->regs[R_CURDESC] = s->desc.nxtdesc;
+        if (prev_d == s->regs[R_TAILDESC]) {
+            s->regs[R_DMASR] |= DMASR_IDLE;
+            break;
+        }
+    }
+}
+
+static
+void axidma_push(void *opaque, unsigned char *buf, size_t len, uint32_t *app)
+{
+    struct XilinxAXIDMA *d = opaque;
+    struct AXIStream *s = &d->streams[1];
+
+    if (!app) {
+        hw_error("No stream app data!\n");
+    }
+    stream_process_s2mem(s, buf, len, app);
+    stream_update_irq(s);
+}
+
+static uint32_t axidma_readl(void *opaque, target_phys_addr_t addr)
+{
+    struct XilinxAXIDMA *d = opaque;
+    struct AXIStream *s;
+    uint32_t r = 0;
+    int sid;
+
+    sid = streamid_from_addr(addr);
+    s = &d->streams[sid];
+
+    addr = addr % 0x30;
+    addr >>= 2;
+    switch (addr) {
+        case R_DMACR:
+            /* Simulate one cycles reset delay.  */
+            s->regs[addr] &= ~DMACR_RESET;
+            r = s->regs[addr];
+            break;
+        case R_DMASR:
+            s->regs[addr] &= 0xffff;
+            s->regs[addr] |= (s->complete_cnt & 0xff) << 16;
+            s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24;
+            r = s->regs[addr];
+            break;
+        default:
+            r = s->regs[addr];
+            D(qemu_log("%s ch=%d addr=" TARGET_FMT_plx " v=%x\n",
+                           __func__, sid, addr * 4, r));
+            break;
+    }
+    return r;
+
+}
+
+static void
+axidma_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    struct XilinxAXIDMA *d = opaque;
+    struct AXIStream *s;
+    int sid;
+
+    sid = streamid_from_addr(addr);
+    s = &d->streams[sid];
+
+    addr = addr % 0x30;
+    addr >>= 2;
+    switch (addr) {
+        case R_DMACR:
+            /* Tailptr mode is always on.  */
+            value |= DMACR_TAILPTR_MODE;
+            /* Remember our previous reset state.  */
+            value |= (s->regs[addr] & DMACR_RESET);
+            s->regs[addr] = value;
+
+            if (value & DMACR_RESET) {
+                stream_reset(s);
+            }
+
+            if ((value & 1) && !stream_resetting(s)) {
+                /* Start processing.  */
+                s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE);
+            }
+            stream_reload_complete_cnt(s);
+            break;
+
+        case R_DMASR:
+            /* Mask away write to clear irq lines.  */
+            value &= ~(value & DMASR_IRQ_MASK);
+            s->regs[addr] = value;
+            break;
+
+        case R_TAILDESC:
+            s->regs[addr] = value;
+            s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle.  */
+            if (!sid) {
+                stream_process_mem2s(s, d->dmach);
+            }
+            break;
+        default:
+            D(qemu_log("%s: ch=%d addr=" TARGET_FMT_plx " v=%x\n",
+                  __func__, sid, addr * 4, value));
+            s->regs[addr] = value;
+            break;
+    }
+    stream_update_irq(s);
+}
+
+static CPUReadMemoryFunc * const axidma_read[] = {
+    &axidma_readl,
+    &axidma_readl,
+    &axidma_readl,
+};
+
+static CPUWriteMemoryFunc * const axidma_write[] = {
+    &axidma_writel,
+    &axidma_writel,
+    &axidma_writel,
+};
+
+static int xilinx_axidma_init(SysBusDevice *dev)
+{
+    struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
+    int axidma_regs;
+    int i;
+
+    sysbus_init_irq(dev, &s->streams[1].irq);
+    sysbus_init_irq(dev, &s->streams[0].irq);
+
+    if (!s->dmach) {
+        hw_error("Unconnected DMA channel.\n");
+    }
+
+    xlx_dma_connect_dma(s->dmach, s, axidma_push);
+
+    axidma_regs = cpu_register_io_memory(axidma_read, axidma_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4 * 2, axidma_regs);
+
+    for (i = 0; i < 2; i++) {
+        stream_reset(&s->streams[i]);
+        s->streams[i].nr = i;
+        s->streams[i].bh = qemu_bh_new(timer_hit, &s->streams[i]);
+        s->streams[i].ptimer = ptimer_init(s->streams[i].bh);
+        ptimer_set_freq(s->streams[i].ptimer, s->freqhz);
+    }
+    return 0;
+}
+
+static SysBusDeviceInfo axidma_info = {
+    .init = xilinx_axidma_init,
+    .qdev.name  = "xilinx,axidma",
+    .qdev.size  = sizeof(struct XilinxAXIDMA),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("freqhz", struct XilinxAXIDMA, freqhz, 50000000),
+        DEFINE_PROP_PTR("dmach", struct XilinxAXIDMA, dmach),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void xilinx_axidma_register(void)
+{
+    sysbus_register_withprop(&axidma_info);
+}
+
+device_init(xilinx_axidma_register)
diff --git a/hw/xilinx_axidma.h b/hw/xilinx_axidma.h
new file mode 100644
index 0000000..37cb6f0
--- /dev/null
+++ b/hw/xilinx_axidma.h
@@ -0,0 +1,39 @@
+/* AXI DMA connection. Used until qdev provides a generic way.  */
+typedef void (*DMAPushFn)(void *opaque,
+                            unsigned char *buf, size_t len, uint32_t *app);
+
+struct XilinxDMAConnection {
+    void *dma;
+    void *client;
+
+    DMAPushFn to_dma;
+    DMAPushFn to_client;
+};
+
+static inline void xlx_dma_connect_client(struct XilinxDMAConnection *dmach,
+                                          void *c, DMAPushFn f)
+{
+    dmach->client = c;
+    dmach->to_client = f;
+}
+
+static inline void xlx_dma_connect_dma(struct XilinxDMAConnection *dmach,
+                                       void *d, DMAPushFn f)
+{
+    dmach->dma = d;
+    dmach->to_dma = f;
+}
+
+static inline
+void xlx_dma_push_to_dma(struct XilinxDMAConnection *dmach,
+                         uint8_t *buf, size_t len, uint32_t *app)
+{
+    dmach->to_dma(dmach->dma, buf, len, app);
+}
+static inline
+void xlx_dma_push_to_client(struct XilinxDMAConnection *dmach,
+                            uint8_t *buf, size_t len, uint32_t *app)
+{
+    dmach->to_client(dmach->client, buf, len, app);
+}
+
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
new file mode 100644
index 0000000..464d275
--- /dev/null
+++ b/hw/xilinx_axienet.c
@@ -0,0 +1,898 @@
+/*
+ * QEMU model of Xilinx AXI-Ethernet.
+ *
+ * Copyright (c) 2011 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#include "xilinx_axidma.h"
+
+#define DPHY(x)
+
+/* Advertisement control register. */
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
+
+struct PHY {
+    uint32_t regs[32];
+
+    int link;
+
+    unsigned int (*read)(struct PHY *phy, unsigned int req);
+    void (*write)(struct PHY *phy, unsigned int req,
+                  unsigned int data);
+};
+
+static unsigned int tdk_read(struct PHY *phy, unsigned int req)
+{
+    int regnum;
+    unsigned r = 0;
+
+    regnum = req & 0x1f;
+
+    switch (regnum) {
+        case 1:
+            if (!phy->link) {
+                break;
+            }
+            /* MR1.  */
+            /* Speeds and modes.  */
+            r |= (1 << 13) | (1 << 14);
+            r |= (1 << 11) | (1 << 12);
+            r |= (1 << 5); /* Autoneg complete.  */
+            r |= (1 << 3); /* Autoneg able.  */
+            r |= (1 << 2); /* link.  */
+            r |= (1 << 1); /* link.  */
+            break;
+        case 5:
+            /* Link partner ability.
+               We are kind; always agree with whatever best mode
+               the guest advertises.  */
+            r = 1 << 14; /* Success.  */
+            /* Copy advertised modes.  */
+            r |= phy->regs[4] & (15 << 5);
+            /* Autoneg support.  */
+            r |= 1;
+            break;
+        case 17:
+            /* Marvel PHY on many xilinx boards.  */
+            r = 0x8000; /* 1000Mb  */
+            break;
+        case 18:
+            {
+                /* Diagnostics reg.  */
+                int duplex = 0;
+                int speed_100 = 0;
+
+                if (!phy->link) {
+                    break;
+                }
+
+                /* Are we advertising 100 half or 100 duplex ? */
+                speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
+                speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
+
+                /* Are we advertising 10 duplex or 100 duplex ? */
+                duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
+                duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
+                r = (speed_100 << 10) | (duplex << 11);
+            }
+            break;
+
+        default:
+            r = phy->regs[regnum];
+            break;
+    }
+    DPHY(qemu_log("\n%s %x = reg[%d]\n", __func__, r, regnum));
+    return r;
+}
+
+static void
+tdk_write(struct PHY *phy, unsigned int req, unsigned int data)
+{
+    int regnum;
+
+    regnum = req & 0x1f;
+    DPHY(qemu_log("%s reg[%d] = %x\n", __func__, regnum, data));
+    switch (regnum) {
+        default:
+            phy->regs[regnum] = data;
+            break;
+    }
+}
+
+static void
+tdk_init(struct PHY *phy)
+{
+    phy->regs[0] = 0x3100;
+    /* PHY Id.  */
+    phy->regs[2] = 0x0300;
+    phy->regs[3] = 0xe400;
+    /* Autonegotiation advertisement reg.  */
+    phy->regs[4] = 0x01E1;
+    phy->link = 1;
+
+    phy->read = tdk_read;
+    phy->write = tdk_write;
+}
+
+struct MDIOBus {
+    /* bus.  */
+    int mdc;
+    int mdio;
+
+    /* decoder.  */
+    enum {
+        PREAMBLE,
+        SOF,
+        OPC,
+        ADDR,
+        REQ,
+        TURNAROUND,
+        DATA
+    } state;
+    unsigned int drive;
+
+    unsigned int cnt;
+    unsigned int addr;
+    unsigned int opc;
+    unsigned int req;
+    unsigned int data;
+
+    struct PHY *devs[32];
+};
+
+static void
+mdio_attach(struct MDIOBus *bus, struct PHY *phy, unsigned int addr)
+{
+    bus->devs[addr & 0x1f] = phy;
+}
+
+#ifdef USE_THIS_DEAD_CODE
+static void
+mdio_detach(struct MDIOBus *bus, struct PHY *phy, unsigned int addr)
+{
+    bus->devs[addr & 0x1f] = NULL;
+}
+#endif
+
+static uint16_t mdio_read_req(struct MDIOBus *bus, unsigned int addr,
+                  unsigned int reg)
+{
+    struct PHY *phy;
+    uint16_t data;
+
+    phy = bus->devs[addr];
+    if (phy && phy->read) {
+        data = phy->read(phy, reg);
+    } else {
+        data = 0xffff;
+    }
+    DPHY(qemu_log("%s addr=%d reg=%d data=%x\n", __func__, addr, reg, data));
+    return data;
+}
+
+static void mdio_write_req(struct MDIOBus *bus, unsigned int addr,
+               unsigned int reg, uint16_t data)
+{
+    struct PHY *phy;
+
+    DPHY(qemu_log("%s addr=%d reg=%d data=%x\n", __func__, addr, reg, data));
+    phy = bus->devs[addr];
+    if (phy && phy->write) {
+        phy->write(phy, reg, data);
+    }
+}
+
+#define DENET(x)
+
+#define R_RAF      (0x000 / 4)
+enum {
+    RAF_MCAST_REJ = (1 << 1),
+    RAF_BCAST_REJ = (1 << 2),
+    RAF_EMCF_EN = (1 << 12),
+    RAF_NEWFUNC_EN = (1 << 11)
+};
+
+#define R_IS       (0x00C / 4)
+enum {
+    IS_HARD_ACCESS_COMPLETE = 1,
+    IS_AUTONEG = (1 << 1),
+    IS_RX_COMPLETE = (1 << 2),
+    IS_RX_REJECT = (1 << 3),
+    IS_TX_COMPLETE = (1 << 5),
+    IS_RX_DCM_LOCK = (1 << 6),
+    IS_MGM_RDY = (1 << 7),
+    IS_PHY_RST_DONE = (1 << 8),
+};
+
+#define R_IP       (0x010 / 4)
+#define R_IE       (0x014 / 4)
+#define R_UAWL     (0x020 / 4)
+#define R_UAWU     (0x024 / 4)
+#define R_PPST     (0x030 / 4)
+enum {
+    PPST_LINKSTATUS = (1 << 0),
+    PPST_PHY_LINKSTATUS = (1 << 7),
+};
+
+#define R_STATS_RX_BYTESL (0x200 / 4)
+#define R_STATS_RX_BYTESH (0x204 / 4)
+#define R_STATS_TX_BYTESL (0x208 / 4)
+#define R_STATS_TX_BYTESH (0x20C / 4)
+#define R_STATS_RXL       (0x290 / 4)
+#define R_STATS_RXH       (0x294 / 4)
+#define R_STATS_RX_BCASTL (0x2a0 / 4)
+#define R_STATS_RX_BCASTH (0x2a4 / 4)
+#define R_STATS_RX_MCASTL (0x2a8 / 4)
+#define R_STATS_RX_MCASTH (0x2ac / 4)
+
+#define R_RCW0     (0x400 / 4)
+#define R_RCW1     (0x404 / 4)
+enum {
+    RCW1_VLAN = (1 << 27),
+    RCW1_RX   = (1 << 28),
+    RCW1_FCS  = (1 << 29),
+    RCW1_JUM  = (1 << 30),
+    RCW1_RST  = (1 << 31),
+};
+
+#define R_TC       (0x408 / 4)
+enum {
+    TC_VLAN = (1 << 27),
+    TC_TX   = (1 << 28),
+    TC_FCS  = (1 << 29),
+    TC_JUM  = (1 << 30),
+    TC_RST  = (1 << 31),
+};
+
+#define R_EMMC     (0x410 / 4)
+enum {
+    EMMC_LINKSPEED_10MB = (0 << 30),
+    EMMC_LINKSPEED_100MB = (1 << 30),
+    EMMC_LINKSPEED_1000MB = (2 << 30),
+};
+
+#define R_PHYC     (0x414 / 4)
+
+#define R_MC       (0x500 / 4)
+#define MC_EN      (1 << 6)
+
+#define R_MCR      (0x504 / 4)
+#define R_MWD      (0x508 / 4)
+#define R_MRD      (0x50c / 4)
+#define R_MIS      (0x600 / 4)
+#define R_MIP      (0x620 / 4)
+#define R_MIE      (0x640 / 4)
+#define R_MIC      (0x640 / 4)
+
+#define R_UAW0     (0x700 / 4)
+#define R_UAW1     (0x704 / 4)
+#define R_FMI      (0x708 / 4)
+#define R_AF0      (0x710 / 4)
+#define R_AF1      (0x714 / 4)
+#define R_MAX      (0x34 / 4)
+
+/* Indirect registers.  */
+struct TEMAC  {
+    struct MDIOBus mdio_bus;
+    struct PHY phy;
+
+    void *parent;
+};
+
+struct XilinxAXIEnet {
+    SysBusDevice busdev;
+    qemu_irq irq;
+    void *dmach;
+    NICState *nic;
+    NICConf conf;
+
+
+    uint32_t c_rxmem;
+    uint32_t c_txmem;
+    uint32_t c_phyaddr;
+
+    struct TEMAC TEMAC;
+
+    /* MII regs.  */
+    union {
+        uint32_t regs[4];
+        struct {
+            uint32_t mc;
+            uint32_t mcr;
+            uint32_t mwd;
+            uint32_t mrd;
+        };
+    } mii;
+
+    struct {
+        uint64_t rx_bytes;
+        uint64_t tx_bytes;
+
+        uint64_t rx;
+        uint64_t rx_bcast;
+        uint64_t rx_mcast;
+    } stats;
+
+    /* Receive configuration words.  */
+    uint32_t rcw[2];
+    /* Transmit config.  */
+    uint32_t tc;
+    uint32_t emmc;
+    uint32_t phyc;
+
+    /* Unicast Address Word.  */
+    uint32_t uaw[2];
+    /* Unicast address filter used with extended mcast.  */
+    uint32_t ext_uaw[2];
+    uint32_t fmi;
+
+    uint32_t regs[R_MAX];
+
+    /* Multicast filter addrs.  */
+    uint32_t maddr[4][2];
+    /* 32K x 1 lookup filter.  */
+    uint32_t ext_mtable[1024];
+
+
+    uint8_t *rxmem;
+};
+
+static void axienet_rx_reset(struct XilinxAXIEnet *s)
+{
+    s->rcw[1] = RCW1_JUM | RCW1_FCS | RCW1_RX | RCW1_VLAN;
+}
+
+static void axienet_tx_reset(struct XilinxAXIEnet *s)
+{
+    s->tc = TC_JUM | TC_TX | TC_VLAN;
+}
+
+static inline int axienet_rx_resetting(struct XilinxAXIEnet *s)
+{
+    return s->rcw[1] & RCW1_RST;
+}
+
+static inline int axienet_rx_enabled(struct XilinxAXIEnet *s)
+{
+    return s->rcw[1] & RCW1_RX;
+}
+
+static inline int axienet_extmcf_enabled(struct XilinxAXIEnet *s)
+{
+    return !!(s->regs[R_RAF] & RAF_EMCF_EN);
+}
+
+static inline int axienet_newfunc_enabled(struct XilinxAXIEnet *s)
+{
+    return !!(s->regs[R_RAF] & RAF_NEWFUNC_EN);
+}
+
+static void axienet_reset(struct XilinxAXIEnet *s)
+{
+    axienet_rx_reset(s);
+    axienet_tx_reset(s);
+
+    s->regs[R_PPST] = PPST_LINKSTATUS | PPST_PHY_LINKSTATUS;
+    s->regs[R_IS] = IS_AUTONEG | IS_RX_DCM_LOCK | IS_MGM_RDY | IS_PHY_RST_DONE;
+
+    s->emmc = EMMC_LINKSPEED_100MB;
+}
+
+static void enet_update_irq(struct XilinxAXIEnet *s)
+{
+    s->regs[R_IP] = s->regs[R_IS] & s->regs[R_IE];
+    qemu_set_irq(s->irq, !!s->regs[R_IP]);
+}
+
+static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
+{
+    struct XilinxAXIEnet *s = opaque;
+    uint32_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+        case R_RCW0:
+        case R_RCW1:
+            r = s->rcw[addr & 1];
+            break;
+
+        case R_TC:
+            r = s->tc;
+            break;
+
+        case R_EMMC:
+            r = s->emmc;
+            break;
+
+        case R_PHYC:
+            r = s->phyc;
+            break;
+
+        case R_MCR:
+            r = s->mii.regs[addr & 3] | (1 << 7); /* Always ready.  */
+            break;
+
+        case R_STATS_RX_BYTESL:
+        case R_STATS_RX_BYTESH:
+            r = s->stats.rx_bytes >> (32 * (addr & 1));
+            break;
+
+        case R_STATS_TX_BYTESL:
+        case R_STATS_TX_BYTESH:
+            r = s->stats.tx_bytes >> (32 * (addr & 1));
+            break;
+
+        case R_STATS_RXL:
+        case R_STATS_RXH:
+            r = s->stats.rx >> (32 * (addr & 1));
+            break;
+        case R_STATS_RX_BCASTL:
+        case R_STATS_RX_BCASTH:
+            r = s->stats.rx_bcast >> (32 * (addr & 1));
+            break;
+        case R_STATS_RX_MCASTL:
+        case R_STATS_RX_MCASTH:
+            r = s->stats.rx_mcast >> (32 * (addr & 1));
+            break;
+
+        case R_MC:
+        case R_MWD:
+        case R_MRD:
+            r = s->mii.regs[addr & 3];
+            break;
+
+        case R_UAW0:
+        case R_UAW1:
+            r = s->uaw[addr & 1];
+            break;
+
+        case R_UAWU:
+        case R_UAWL:
+            r = s->ext_uaw[addr & 1];
+            break;
+
+        case R_FMI:
+            r = s->fmi;
+            break;
+
+        case R_AF0:
+        case R_AF1:
+            r = s->maddr[s->fmi & 3][addr & 1];
+            break;
+
+        case 0x8000 ... 0x83ff:
+            r = s->ext_mtable[addr - 0x8000];
+            break;
+
+        default:
+            if (addr < ARRAY_SIZE(s->regs)) {
+                r = s->regs[addr];
+            }
+            DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
+                            __func__, addr * 4, r));
+            break;
+    }
+    return r;
+}
+
+static void
+enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    struct XilinxAXIEnet *s = opaque;
+    struct TEMAC *t = &s->TEMAC;
+
+    addr >>= 2;
+    switch (addr) {
+        case R_RCW0:
+        case R_RCW1:
+            s->rcw[addr & 1] = value;
+            if ((addr & 1) && value & RCW1_RST) {
+                axienet_rx_reset(s);
+            }
+            break;
+
+        case R_TC:
+            s->tc = value;
+            if (value & TC_RST) {
+                axienet_tx_reset(s);
+            }
+            break;
+
+        case R_EMMC:
+            s->emmc = value;
+            break;
+
+        case R_PHYC:
+            s->phyc = value;
+            break;
+
+        case R_MC:
+             value &= ((1 < 7) - 1);
+
+             /* Enable the MII.  */
+             if (value & MC_EN) {
+                 unsigned int miiclkdiv = value & ((1 << 6) - 1);
+                 if (!miiclkdiv) {
+                     qemu_log("AXIENET: MDIO enabled but MDIOCLK is zero!\n");
+                 }
+             }
+             s->mii.mc = value;
+             break;
+
+        case R_MCR: {
+             unsigned int phyaddr = (value >> 24) & 0x1f;
+             unsigned int regaddr = (value >> 16) & 0x1f;
+             unsigned int op = (value >> 14) & 3;
+             unsigned int initiate = (value >> 11) & 1;
+
+             if (initiate) {
+                 if (op == 1) {
+                     mdio_write_req(&t->mdio_bus, phyaddr, regaddr, s->mii.mwd);
+                 } else if (op == 2) {
+                     s->mii.mrd = mdio_read_req(&t->mdio_bus, phyaddr, regaddr);
+                 } else {
+                     qemu_log("AXIENET: invalid MDIOBus OP=%d\n", op);
+                 }
+             }
+             s->mii.mcr = value;
+             break;
+        }
+
+        case R_MWD:
+        case R_MRD:
+             s->mii.regs[addr & 3] = value;
+             break;
+
+
+        case R_UAW0:
+        case R_UAW1:
+            s->uaw[addr & 1] = value;
+            break;
+
+        case R_UAWL:
+        case R_UAWU:
+            s->ext_uaw[addr & 1] = value;
+            break;
+
+        case R_FMI:
+            s->fmi = value;
+            break;
+
+        case R_AF0:
+        case R_AF1:
+            s->maddr[s->fmi & 3][addr & 1] = value;
+            break;
+
+        case 0x8000 ... 0x83ff:
+            s->ext_mtable[addr - 0x8000] = value;
+            break;
+
+        default:
+            DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
+                           __func__, addr * 4, value));
+            if (addr < ARRAY_SIZE(s->regs)) {
+                s->regs[addr] = value;
+            }
+            break;
+    }
+    enet_update_irq(s);
+}
+
+static CPUReadMemoryFunc * const enet_read[] = {
+    &enet_readl,
+    &enet_readl,
+    &enet_readl,
+};
+
+static CPUWriteMemoryFunc * const enet_write[] = {
+    &enet_writel,
+    &enet_writel,
+    &enet_writel,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return !axienet_rx_resetting(s) && axienet_rx_enabled(s);
+}
+
+static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1)
+{
+    int match = 1;
+
+    if (memcmp(buf, &f0, 4)) {
+        match = 0;
+    }
+
+    if (buf[4] != (f1 & 0xff) || buf[5] != ((f1 >> 8) & 0xff)) {
+        match = 0;
+    }
+
+    return match;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
+    uint32_t app[6] = {0};
+    int promisc = s->fmi & (1 << 31);
+    int unicast, broadcast, multicast, ip_multicast = 0;
+    uint32_t csum32;
+    uint16_t csum16;
+    int i;
+
+    s = s;
+    DENET(qemu_log("%s: %zd bytes\n", __func__, size));
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (multicast && (memcmp(sa_ipmcast, buf, sizeof sa_ipmcast) == 0)) {
+        ip_multicast = 1;
+    }
+
+    /* Jumbo or vlan sizes ?  */
+    if (!(s->rcw[1] & RCW1_JUM)) {
+        if (size > 1518 && size <= 1522 && !(s->rcw[1] & RCW1_VLAN)) {
+            return size;
+        }
+    }
+
+    /* Basic Address filters.  If you want to use the extended filters
+       you'll generally have to place the ethernet mac into promiscuous mode
+       to avoid the basic filtering from dropping most frames.  */
+    if (!promisc) {
+        if (unicast) {
+            if (!enet_match_addr(buf, s->uaw[0], s->uaw[1])) {
+                return size;
+            }
+        } else {
+            if (broadcast) {
+                /* Broadcast.  */
+                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
+                    return size;
+                }
+            } else {
+                int drop = 1;
+
+                /* Multicast.  */
+                if (s->regs[R_RAF] & RAF_MCAST_REJ) {
+                    return size;
+                }
+
+                for (i = 0; i < 4; i++) {
+                    if (enet_match_addr(buf, s->maddr[i][0], s->maddr[i][1])) {
+                        drop = 0;
+                        break;
+                    }
+                }
+
+                if (drop) {
+                    return size;
+                }
+            }
+        }
+    }
+
+    /* Extended mcast filtering enabled?  */
+    if (axienet_newfunc_enabled(s) && axienet_extmcf_enabled(s)) {
+        if (unicast) {
+            if (!enet_match_addr(buf, s->ext_uaw[0], s->ext_uaw[1])) {
+                return size;
+            }
+        } else {
+            if (broadcast) {
+                /* Broadcast. ???  */
+                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
+                    return size;
+                }
+            } else {
+                int idx, bit;
+
+                /* Multicast.  */
+                if (!memcmp(buf, sa_ipmcast, 3)) {
+                    return size;
+                }
+
+                idx  = (buf[4] & 0x7f) << 8;
+                idx |= buf[5];
+
+                bit = 1 << (idx & 0x1f);
+                idx >>= 5;
+
+                if (!(s->ext_mtable[idx] & bit)) {
+                    return size;
+                }
+            }
+        }
+    }
+
+    if (size < 12) {
+        s->regs[R_IS] |= IS_RX_REJECT;
+        enet_update_irq(s);
+        return -1;
+    }
+
+    if (size > (s->c_rxmem - 4)) {
+        size = s->c_rxmem - 4;
+    }
+
+    memcpy(s->rxmem, buf, size);
+    memset(s->rxmem + size, 0, 4); /* Clear the FCS.  */
+
+    if (s->rcw[1] & RCW1_FCS) {
+        size += 4; /* fcs is inband.  */
+    }
+
+    app[0] = 5 << 28;
+    csum32 = net_checksum_add(size - 14, (uint8_t *)s->rxmem + 14);
+    /* Fold it once.  */
+    csum32 = (csum32 & 0xffff) + (csum32 >> 16);
+    /* And twice to get rid of possible carries.  */
+    csum16 = (csum32 & 0xffff) + (csum32 >> 16);
+    app[3] = csum16;
+    app[4] = size & 0xffff;
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+        app[2] |= 1 | (ip_multicast << 1);
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+        app[2] |= 1 << 3;
+    }
+
+    /* Good frame.  */
+    app[2] |= 1 << 6;
+
+    xlx_dma_push_to_dma(s->dmach, (void *)s->rxmem, size, app);
+
+    s->regs[R_IS] |= IS_RX_COMPLETE;
+    enet_update_irq(s);
+    return size;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    /* FIXME.  */
+    struct XilinxAXIEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    qemu_free(s->rxmem);
+    qemu_free(s);
+}
+
+static void
+axienet_stream_push(void *opaque, uint8_t *buf, size_t size, uint32_t *hdr)
+{
+    struct XilinxAXIEnet *s = opaque;
+
+    /* TX enable ?  */
+    if (!(s->tc & TC_TX)) {
+        return;
+    }
+
+    /* Jumbo or vlan sizes ?  */
+    if (!(s->tc & TC_JUM)) {
+        if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) {
+            return;
+        }
+    }
+
+    if (hdr[0] & 1) {
+        unsigned int start_off = hdr[1] >> 16;
+        unsigned int write_off = hdr[1] & 0xffff;
+        uint32_t tmp_csum;
+        uint16_t csum;
+
+        tmp_csum = net_checksum_add(size - start_off,
+                                    (uint8_t *)buf + start_off);
+        /* Accumulate the seed.  */
+        tmp_csum += hdr[2] & 0xffff;
+
+        /* Fold the 32bit partial checksum.  */
+        csum = net_checksum_finish(tmp_csum);
+
+        /* Writeback.  */
+        buf[write_off] = csum >> 8;
+        buf[write_off + 1] = csum & 0xff;
+    }
+
+    qemu_send_packet(&s->nic->nc, buf, size);
+
+    s->stats.tx_bytes += size;
+    s->regs[R_IS] |= IS_TX_COMPLETE;
+    enet_update_irq(s);
+}
+
+static NetClientInfo net_xilinx_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xilinx_enet_init(SysBusDevice *dev)
+{
+    struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
+    int enet_regs;
+
+    sysbus_init_irq(dev, &s->irq);
+
+    if (!s->dmach) {
+        hw_error("Unconnected Xilinx Ethernet MAC.\n");
+    }
+
+    xlx_dma_connect_client(s->dmach, s, axienet_stream_push);
+
+    enet_regs = cpu_register_io_memory(enet_read, enet_write, s,
+                                       DEVICE_LITTLE_ENDIAN);
+    sysbus_init_mmio(dev, 0x40000, enet_regs);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    tdk_init(&s->TEMAC.phy);
+    mdio_attach(&s->TEMAC.mdio_bus, &s->TEMAC.phy, s->c_phyaddr);
+
+    s->TEMAC.parent = s;
+
+    s->rxmem = qemu_malloc(s->c_rxmem);
+    axienet_reset(s);
+
+    return 0;
+}
+
+static SysBusDeviceInfo xilinx_enet_info = {
+    .init = xilinx_enet_init,
+    .qdev.name  = "xilinx,axienet",
+    .qdev.size  = sizeof(struct XilinxAXIEnet),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("phyaddr", struct XilinxAXIEnet, c_phyaddr, 7),
+        DEFINE_PROP_UINT32("c_rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
+        DEFINE_PROP_UINT32("c_txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
+        DEFINE_PROP_PTR("dmach", struct XilinxAXIEnet, dmach),
+        DEFINE_NIC_PROPERTIES(struct XilinxAXIEnet, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xilinx_enet_register(void)
+{
+    sysbus_register_withprop(&xilinx_enet_info);
+}
+
+device_init(xilinx_enet_register)
commit d746ce6dbaa91766e473f6fff82dfbd88ba3f86d
Author: Michal Simek <monstr at monstr.eu>
Date:   Fri Mar 4 14:40:29 2011 +0100

    microblaze: Compile uart 16550 serial driver
    
    Upcomming little endian platform will use 16550 serial driver.
    
    Signed-off-by: Michal Simek <monstr at monstr.eu>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak
index 4399b8b..613edab 100644
--- a/default-configs/microblaze-softmmu.mak
+++ b/default-configs/microblaze-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI01=y
+CONFIG_SERIAL=y
diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak
index ddc6bf4..4b40fb2 100644
--- a/default-configs/microblazeel-softmmu.mak
+++ b/default-configs/microblazeel-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI01=y
+CONFIG_SERIAL=y
commit 03feae73056ba3223151c31871860e30630645ac
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Feb 14 17:49:46 2011 +0100

    Add qcow2 documentation
    
    This adds a description of the qcow2 file format to the docs/ directory.
    Besides documenting what's there, which is never wrong, the document should
    provide a good basis for the discussion of format extensions (called "qcow3"
    in previous discussions)
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt
new file mode 100644
index 0000000..8fc3cb2
--- /dev/null
+++ b/docs/specs/qcow2.txt
@@ -0,0 +1,260 @@
+== General ==
+
+A qcow2 image file is organized in units of constant size, which are called
+(host) clusters. A cluster is the unit in which all allocations are done,
+both for actual guest data and for image metadata.
+
+Likewise, the virtual disk as seen by the guest is divided into (guest)
+clusters of the same size.
+
+All numbers in qcow2 are stored in Big Endian byte order.
+
+
+== Header ==
+
+The first cluster of a qcow2 image contains the file header:
+
+    Byte  0 -  3:   magic
+                    QCOW magic string ("QFI\xfb")
+
+          4 -  7:   version
+                    Version number (only valid value is 2)
+
+          8 - 15:   backing_file_offset
+                    Offset into the image file at which the backing file name
+                    is stored (NB: The string is not null terminated). 0 if the
+                    image doesn't have a backing file.
+
+         16 - 19:   backing_file_size
+                    Length of the backing file name in bytes. Must not be
+                    longer than 1023 bytes. Undefined if the image doesn't have
+                    a backing file.
+
+         20 - 23:   cluster_bits
+                    Number of bits that are used for addressing an offset
+                    within a cluster (1 << cluster_bits is the cluster size).
+                    Must not be less than 9 (i.e. 512 byte clusters).
+
+                    Note: qemu as of today has an implementation limit of 2 MB
+                    as the maximum cluster size and won't be able to open images
+                    with larger cluster sizes.
+
+         24 - 31:   size
+                    Virtual disk size in bytes
+
+         32 - 35:   crypt_method
+                    0 for no encryption
+                    1 for AES encryption
+
+         36 - 39:   l1_size
+                    Number of entries in the active L1 table
+
+         40 - 47:   l1_table_offset
+                    Offset into the image file at which the active L1 table
+                    starts. Must be aligned to a cluster boundary.
+
+         48 - 55:   refcount_table_offset
+                    Offset into the image file at which the refcount table
+                    starts. Must be aligned to a cluster boundary.
+
+         56 - 59:   refcount_table_clusters
+                    Number of clusters that the refcount table occupies
+
+         60 - 63:   nb_snapshots
+                    Number of snapshots contained in the image
+
+         64 - 71:   snapshots_offset
+                    Offset into the image file at which the snapshot table
+                    starts. Must be aligned to a cluster boundary.
+
+Directly after the image header, optional sections called header extensions can
+be stored. Each extension has a structure like the following:
+
+    Byte  0 -  3:   Header extension type:
+                        0x00000000 - End of the header extension area
+                        0xE2792ACA - Backing file format name
+                        other      - Unknown header extension, can be safely
+                                     ignored
+
+          4 -  7:   Length of the header extension data
+
+          8 -  n:   Header extension data
+
+          n -  m:   Padding to round up the header extension size to the next
+                    multiple of 8.
+
+The remaining space between the end of the header extension area and the end of
+the first cluster can be used for other data. Usually, the backing file name is
+stored there.
+
+
+== Host cluster management ==
+
+qcow2 manages the allocation of host clusters by maintaining a reference count
+for each host cluster. A refcount of 0 means that the cluster is free, 1 means
+that it is used, and >= 2 means that it is used and any write access must
+perform a COW (copy on write) operation.
+
+The refcounts are managed in a two-level table. The first level is called
+refcount table and has a variable size (which is stored in the header). The
+refcount table can cover multiple clusters, however it needs to be contiguous
+in the image file.
+
+It contains pointers to the second level structures which are called refcount
+blocks and are exactly one cluster in size.
+
+Given a offset into the image file, the refcount of its cluster can be obtained
+as follows:
+
+    refcount_block_entries = (cluster_size / sizeof(uint16_t))
+
+    refcount_block_index = (offset / cluster_size) % refcount_table_entries
+    refcount_table_index = (offset / cluster_size) / refcount_table_entries
+
+    refcount_block = load_cluster(refcount_table[refcount_table_index]);
+    return refcount_block[refcount_block_index];
+
+Refcount table entry:
+
+    Bit  0 -  8:    Reserved (set to 0)
+
+         9 - 63:    Bits 9-63 of the offset into the image file at which the
+                    refcount block starts. Must be aligned to a cluster
+                    boundary.
+
+                    If this is 0, the corresponding refcount block has not yet
+                    been allocated. All refcounts managed by this refcount block
+                    are 0.
+
+Refcount block entry:
+
+    Bit  0 - 15:    Reference count of the cluster
+
+
+== Cluster mapping ==
+
+Just as for refcounts, qcow2 uses a two-level structure for the mapping of
+guest clusters to host clusters. They are called L1 and L2 table.
+
+The L1 table has a variable size (stored in the header) and may use multiple
+clusters, however it must be contiguous in the image file. L2 tables are
+exactly one cluster in size.
+
+Given a offset into the virtual disk, the offset into the image file can be
+obtained as follows:
+
+    l2_entries = (cluster_size / sizeof(uint64_t))
+
+    l2_index = (offset / cluster_size) % l2_entries
+    l1_index = (offset / cluster_size) / l2_entries
+
+    l2_table = load_cluster(l1_table[l1_index]);
+    cluster_offset = l2_table[l2_index];
+
+    return cluster_offset + (offset % cluster_size)
+
+L1 table entry:
+
+    Bit  0 -  8:    Reserved (set to 0)
+
+         9 - 55:    Bits 9-55 of the offset into the image file at which the L2
+                    table starts. Must be aligned to a cluster boundary. If the
+                    offset is 0, the L2 table and all clusters described by this
+                    L2 table are unallocated.
+
+        56 - 62:    Reserved (set to 0)
+
+             63:    0 for an L2 table that is unused or requires COW, 1 if its
+                    refcount is exactly one. This information is only accurate
+                    in the active L1 table.
+
+L2 table entry (for normal clusters):
+
+    Bit  0 -  8:    Reserved (set to 0)
+
+         9 - 55:    Bits 9-55 of host cluster offset. Must be aligned to a
+                    cluster boundary. If the offset is 0, the cluster is
+                    unallocated.
+
+        56 - 61:    Reserved (set to 0)
+
+             62:    0 (this cluster is not compressed)
+
+             63:    0 for a cluster that is unused or requires COW, 1 if its
+                    refcount is exactly one. This information is only accurate
+                    in L2 tables that are reachable from the the active L1
+                    table.
+
+L2 table entry (for compressed clusters; x = 62 - (cluster_size - 8)):
+
+    Bit  0 -  x:    Host cluster offset. This is usually _not_ aligned to a
+                    cluster boundary!
+
+       x+1 - 61:    Compressed size of the images in sectors of 512 bytes
+
+             62:    1 (this cluster is compressed using zlib)
+
+             63:    0 for a cluster that is unused or requires COW, 1 if its
+                    refcount is exactly one. This information is only accurate
+                    in L2 tables that are reachable from the the active L1
+                    table.
+
+If a cluster is unallocated, read requests shall read the data from the backing
+file. If there is no backing file or the backing file is smaller than the image,
+they shall read zeros for all parts that are not covered by the backing file.
+
+
+== Snapshots ==
+
+qcow2 supports internal snapshots. Their basic principle of operation is to
+switch the active L1 table, so that a different set of host clusters are
+exposed to the guest.
+
+When creating a snapshot, the L1 table should be copied and the refcount of all
+L2 tables and clusters reachable form this L1 table must be increased, so that
+a write causes a COW and isn't visible in other snapshots.
+
+When loading a snapshot, bit 63 of all entries in the new active L1 table and
+all L2 tables referenced by it must be reconstructed from the refcount table
+as it doesn't need to be accurate in inactive L1 tables.
+
+A directory of all snapshots is stored in the snapshot table, a contiguous area
+in the image file, whose starting offset and length are given by the header
+fields snapshots_offset and nb_snapshots. The entries of the snapshot table
+have variable length, depending on the length of ID, name and extra data.
+
+Snapshot table entry:
+
+    Byte 0 -  7:    Offset into the image file at which the L1 table for the
+                    snapshot starts. Must be aligned to a cluster boundary.
+
+         8 - 11:    Number of entries in the L1 table of the snapshots
+
+        12 - 13:    Length of the unique ID string describing the snapshot
+
+        14 - 15:    Length of the name of the snapshot
+
+        16 - 19:    Time at which the snapshot was taken in seconds since the
+                    Epoch
+
+        20 - 23:    Subsecond part of the time at which the snapshot was taken
+                    in nanoseconds
+
+        24 - 31:    Time that the guest was running until the snapshot was
+                    taken in nanoseconds
+
+        32 - 35:    Size of the VM state in bytes. 0 if no VM state is saved.
+                    If there is VM state, it starts at the first cluster
+                    described by first L1 table entry that doesn't describe a
+                    regular guest cluster (i.e. VM state is stored like guest
+                    disk content, except that it is stored at offsets that are
+                    larger than the virtual disk presented to the guest)
+
+        36 - 39:    Size of extra data in the table entry (used for future
+                    extensions of the format)
+
+        variable:   Extra data for future extensions. Must be ignored.
+
+        variable:   Unique ID string for the snapshot (not null terminated)
+
+        variable:   Name of the snapshot (not null terminated)
commit ad620c29c2da573e3a5f13f5b1eb2694fee64cfb
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 13 10:30:52 2011 +0000

    win32: implement missing timersub
    
    Implement and wrap timersub() for Win32.
    
    Acked-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/osdep.h b/osdep.h
index 27eedcf..5e48860 100644
--- a/osdep.h
+++ b/osdep.h
@@ -8,9 +8,7 @@
 #include <sys/signal.h>
 #endif
 
-#ifndef _WIN32
 #include <sys/time.h>
-#endif
 
 #ifndef glue
 #define xglue(x, y) x ## y
@@ -131,4 +129,21 @@ int qemu_madvise(void *addr, size_t len, int advice);
 
 int qemu_create_pidfile(const char *filename);
 
+#ifdef _WIN32
+static inline void qemu_timersub(const struct timeval *val1,
+                                 const struct timeval *val2,
+                                 struct timeval *res)
+{
+    res->tv_sec = val1->tv_sec - val2->tv_sec;
+    if (val1->tv_usec < val2->tv_usec) {
+        res->tv_sec--;
+        res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000;
+    } else {
+        res->tv_usec = val1->tv_usec - val2->tv_usec;
+    }
+}
+#else
+#define qemu_timersub timersub
+#endif
+
 #endif
diff --git a/ui/vnc.c b/ui/vnc.c
index 34dc0cd..1b68965 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2302,7 +2302,7 @@ static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
         }
     }
 
-    timersub(tv, &VNC_REFRESH_STATS, &res);
+    qemu_timersub(tv, &VNC_REFRESH_STATS, &res);
 
     if (timercmp(&vd->guest.last_freq_check, &res, >)) {
         return has_dirty;
@@ -2320,7 +2320,7 @@ static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
             }
 
             max = rect->times[(rect->idx + count - 1) % count];
-            timersub(tv, &max, &res);
+            qemu_timersub(tv, &max, &res);
 
             if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
                 rect->freq = 0;
@@ -2331,7 +2331,7 @@ static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
 
             min = rect->times[rect->idx];
             max = rect->times[(rect->idx + count - 1) % count];
-            timersub(&max, &min, &res);
+            qemu_timersub(&max, &min, &res);
 
             rect->freq = res.tv_sec + res.tv_usec / 1000000.;
             rect->freq /= count;
commit 31d3c9b8c15d7b42f508d5fc2adc4abb7c732b70
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sun Mar 13 20:14:30 2011 +0000

    simpletrace: Move st_init() error reporting
    
    User emulator builds do not have error_report() so it should not be used
    by simpletrace.c.  In fact, error reporting inside simpletrace.c is
    inappropriate and should be done by the caller instead.
    
    This patch moves st_init() error reporting out to its caller,
    vl.c:main().
    
    Reported-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/simpletrace.c b/simpletrace.c
index 9926ab3..f1dbb5e 100644
--- a/simpletrace.c
+++ b/simpletrace.c
@@ -14,7 +14,6 @@
 #include <time.h>
 #include <signal.h>
 #include <pthread.h>
-#include "qerror.h"
 #include "qemu-timer.h"
 #include "trace.h"
 
@@ -331,7 +330,7 @@ void st_flush_trace_buffer(void)
     flush_trace_file(true);
 }
 
-void st_init(const char *file)
+bool st_init(const char *file)
 {
     pthread_t thread;
     pthread_attr_t attr;
@@ -347,10 +346,10 @@ void st_init(const char *file)
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
 
     if (ret != 0) {
-        error_report("warning: unable to create trace file thread\n");
-        return;
+        return false;
     }
 
     atexit(st_flush_trace_buffer);
     st_set_trace_file(file);
+    return true;
 }
diff --git a/simpletrace.h b/simpletrace.h
index 3a5bd9f..8d893bd 100644
--- a/simpletrace.h
+++ b/simpletrace.h
@@ -37,11 +37,11 @@ void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
 void st_set_trace_file_enabled(bool enable);
 bool st_set_trace_file(const char *file);
 void st_flush_trace_buffer(void);
-void st_init(const char *file);
+bool st_init(const char *file);
 #else
-static inline void st_init(const char *file)
+static inline bool st_init(const char *file)
 {
-    /* Do nothing */
+    return true;
 }
 #endif /* !CONFIG_SIMPLE_TRACE */
 
diff --git a/vl.c b/vl.c
index 5e007a7..b1a94aa 100644
--- a/vl.c
+++ b/vl.c
@@ -2766,7 +2766,9 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();
 
-    st_init(trace_file);
+    if (!st_init(trace_file)) {
+        fprintf(stderr, "warning: unable to initialize simple trace backend\n");
+    }
 
     /* If no data_dir is specified then try to find it relative to the
        executable path.  */
commit fd28aa132362320f9f3a30b23f634bb14dee528e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:14 2011 +0100

    s390: Detect invalid invocations of qemu_ram_free/remap
    
    This both detects invalid invocations of qemu_ram_free and
    qemu_ram_remap when mem_path is non-NULL and fixes a build error on
    s390 ("'area' may be used uninitialized in this function").
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Alexander Graf <agraf at suse.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/exec.c b/exec.c
index 723ace4..c5358c3 100644
--- a/exec.c
+++ b/exec.c
@@ -2931,6 +2931,8 @@ void qemu_ram_free(ram_addr_t addr)
                 } else {
                     qemu_vfree(block->host);
                 }
+#else
+                abort();
 #endif
             } else {
 #if defined(TARGET_S390X) && defined(CONFIG_KVM)
@@ -2979,6 +2981,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
                         area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
                                     flags, -1, 0);
                     }
+#else
+                    abort();
 #endif
                 } else {
 #if defined(TARGET_S390X) && defined(CONFIG_KVM)
commit 1009d2edea4acd5b683ab1572ad7f4d4583e1860
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:13 2011 +0100

    x86: Unbreak TCG support for hardware breakpoints
    
    Commit 83f338f73e broke x86 hardware breakpoint emulation by moving the
    debug exception handling out of cpu_exec. Fix this by moving all TCG
    related bits back, only leaving the generic guest debugging parts in
    cpus.c.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: TeLeMan <geleman at gmail.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 34eaedc..5cc9379 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -196,6 +196,30 @@ static inline TranslationBlock *tb_find_fast(void)
     return tb;
 }
 
+static CPUDebugExcpHandler *debug_excp_handler;
+
+CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
+{
+    CPUDebugExcpHandler *old_handler = debug_excp_handler;
+
+    debug_excp_handler = handler;
+    return old_handler;
+}
+
+static void cpu_handle_debug_exception(CPUState *env)
+{
+    CPUWatchpoint *wp;
+
+    if (!env->watchpoint_hit) {
+        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
+            wp->flags &= ~BP_WATCHPOINT_HIT;
+        }
+    }
+    if (debug_excp_handler) {
+        debug_excp_handler(env);
+    }
+}
+
 /* main execution loop */
 
 volatile sig_atomic_t exit_request;
@@ -269,6 +293,9 @@ int cpu_exec(CPUState *env1)
                 if (env->exception_index >= EXCP_INTERRUPT) {
                     /* exit request from the cpu execution loop */
                     ret = env->exception_index;
+                    if (ret == EXCP_DEBUG) {
+                        cpu_handle_debug_exception(env);
+                    }
                     break;
                 } else {
 #if defined(CONFIG_USER_ONLY)
diff --git a/cpus.c b/cpus.c
index 26e5bba..975a6ce 100644
--- a/cpus.c
+++ b/cpus.c
@@ -166,29 +166,8 @@ static bool all_cpu_threads_idle(void)
     return true;
 }
 
-static CPUDebugExcpHandler *debug_excp_handler;
-
-CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
-{
-    CPUDebugExcpHandler *old_handler = debug_excp_handler;
-
-    debug_excp_handler = handler;
-    return old_handler;
-}
-
-static void cpu_handle_debug_exception(CPUState *env)
+static void cpu_handle_guest_debug(CPUState *env)
 {
-    CPUWatchpoint *wp;
-
-    if (!env->watchpoint_hit) {
-        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
-            wp->flags &= ~BP_WATCHPOINT_HIT;
-        }
-    }
-    if (debug_excp_handler) {
-        debug_excp_handler(env);
-    }
-
     gdb_set_stop_cpu(env);
     qemu_system_debug_request();
 #ifdef CONFIG_IOTHREAD
@@ -818,7 +797,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
         if (cpu_can_run(env)) {
             r = kvm_cpu_exec(env);
             if (r == EXCP_DEBUG) {
-                cpu_handle_debug_exception(env);
+                cpu_handle_guest_debug(env);
             }
         }
         qemu_kvm_wait_io_event(env);
@@ -1110,7 +1089,7 @@ bool cpu_exec_all(void)
                 r = tcg_cpu_exec(env);
             }
             if (r == EXCP_DEBUG) {
-                cpu_handle_debug_exception(env);
+                cpu_handle_guest_debug(env);
                 break;
             }
         } else if (env->stop || env->stopped) {
commit 1ab3c6c07382c4249854f811cd6182a0a88e25fb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Mar 15 12:26:12 2011 +0100

    Implement qemu_kvm_eat_signals only for CONFIG_LINUX
    
    qemu_kvm_eat_signals requires POSIX support with realtime extensions for
    sigtimedwait. Not all our target platforms provide this. Moreover,
    undefined sigbus_reraise was referenced on non-Linux as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 077729c..26e5bba 100644
--- a/cpus.c
+++ b/cpus.c
@@ -245,11 +245,58 @@ static void qemu_init_sigbus(void)
     prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
 }
 
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+    struct timespec ts = { 0, 0 };
+    siginfo_t siginfo;
+    sigset_t waitset;
+    sigset_t chkset;
+    int r;
+
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIG_IPI);
+    sigaddset(&waitset, SIGBUS);
+
+    do {
+        r = sigtimedwait(&waitset, &siginfo, &ts);
+        if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
+            perror("sigtimedwait");
+            exit(1);
+        }
+
+        switch (r) {
+        case SIGBUS:
+            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
+                sigbus_reraise();
+            }
+            break;
+        default:
+            break;
+        }
+
+        r = sigpending(&chkset);
+        if (r == -1) {
+            perror("sigpending");
+            exit(1);
+        }
+    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
+
+#ifndef CONFIG_IOTHREAD
+    if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
+        qemu_notify_event();
+    }
+#endif
+}
+
 #else /* !CONFIG_LINUX */
 
 static void qemu_init_sigbus(void)
 {
 }
+
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+}
 #endif /* !CONFIG_LINUX */
 
 #ifndef _WIN32
@@ -455,49 +502,6 @@ static void qemu_tcg_init_cpu_signals(void)
 #endif
 }
 
-static void qemu_kvm_eat_signals(CPUState *env)
-{
-    struct timespec ts = { 0, 0 };
-    siginfo_t siginfo;
-    sigset_t waitset;
-    sigset_t chkset;
-    int r;
-
-    sigemptyset(&waitset);
-    sigaddset(&waitset, SIG_IPI);
-    sigaddset(&waitset, SIGBUS);
-
-    do {
-        r = sigtimedwait(&waitset, &siginfo, &ts);
-        if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
-            perror("sigtimedwait");
-            exit(1);
-        }
-
-        switch (r) {
-        case SIGBUS:
-            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
-                sigbus_reraise();
-            }
-            break;
-        default:
-            break;
-        }
-
-        r = sigpending(&chkset);
-        if (r == -1) {
-            perror("sigpending");
-            exit(1);
-        }
-    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
-
-#ifndef CONFIG_IOTHREAD
-    if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
-        qemu_notify_event();
-    }
-#endif
-}
-
 #else /* _WIN32 */
 
 HANDLE qemu_event_handle;
@@ -526,10 +530,6 @@ static void qemu_event_increment(void)
     }
 }
 
-static void qemu_kvm_eat_signals(CPUState *env)
-{
-}
-
 static int qemu_signal_init(void)
 {
     return 0;
commit 209bef3e014ba1613759575e2c10f0ef8d64eb84
Author: Feiran Zheng <famcool at gmail.com>
Date:   Wed Mar 9 21:19:35 2011 +0800

    hw/xen_disk: aio_inflight not released in handling ioreq when nr_segments==0
    
    In hw/xen_disk.c, async writing ioreq is leaked when
    ioreq->req.nr_segments==0, because `aio_inflight` flag is not released
    properly (skipped by misplaced "break").
    
    Signed-off-by: Feiran Zheng <famcool at gmail.com>
    Acked-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index ed9e5eb..445bf03 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -408,9 +408,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
 	break;
     case BLKIF_OP_WRITE:
     case BLKIF_OP_WRITE_BARRIER:
-        ioreq->aio_inflight++;
         if (!ioreq->req.nr_segments)
             break;
+        ioreq->aio_inflight++;
         bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
                         &ioreq->v, ioreq->v.size / BLOCK_SIZE,
                         qemu_aio_complete, ioreq);
commit 52f9a172b6db89ba1f4389883be805d65dd3ca8c
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 9 11:20:30 2011 +0100

    Improve error handling in do_snapshot_blkdev()
    
    In case we cannot open the newly created snapshot image, try to fall
    back to the original image file and continue running on that, which
    should prevent the guest from aborting.
    
    This is a corner case which can happen if the admin by mistake
    specifies the snapshot file on a virtual file system which does not
    support O_DIRECT. bdrv_create() does not use O_DIRECT, but the
    following open in bdrv_open() does and will then fail.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 0690cc8..ecf2252 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -574,9 +574,10 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     const char *filename = qdict_get_try_str(qdict, "snapshot_file");
     const char *format = qdict_get_try_str(qdict, "format");
     BlockDriverState *bs;
-    BlockDriver *drv, *proto_drv;
+    BlockDriver *drv, *old_drv, *proto_drv;
     int ret = 0;
     int flags;
+    char old_filename[1024];
 
     if (!filename) {
         qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
@@ -591,6 +592,11 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
         goto out;
     }
 
+    pstrcpy(old_filename, sizeof(old_filename), bs->filename);
+
+    old_drv = bs->drv;
+    flags = bs->open_flags;
+
     if (!format) {
         format = "qcow2";
     }
@@ -610,7 +616,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     ret = bdrv_img_create(filename, format, bs->filename,
-                          bs->drv->format_name, NULL, -1, bs->open_flags);
+                          bs->drv->format_name, NULL, -1, flags);
     if (ret) {
         goto out;
     }
@@ -618,15 +624,20 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     qemu_aio_flush();
     bdrv_flush(bs);
 
-    flags = bs->open_flags;
     bdrv_close(bs);
     ret = bdrv_open(bs, filename, flags, drv);
     /*
-     * If reopening the image file we just created fails, we really
-     * are in trouble :(
+     * If reopening the image file we just created fails, fall back
+     * and try to re-open the original image. If that fails too, we
+     * are in serious trouble.
      */
     if (ret != 0) {
-        abort();
+        ret = bdrv_open(bs, old_filename, flags, old_drv);
+        if (ret != 0) {
+            qerror_report(QERR_OPEN_FILE_FAILED, old_filename);
+        } else {
+            qerror_report(QERR_OPEN_FILE_FAILED, filename);
+        }
     }
 out:
     if (ret) {
commit b93af93d2bbacf034af1888c96291850aa849b59
Author: Brian Wheeler <bdwheele at indiana.edu>
Date:   Tue Mar 1 08:30:23 2011 -0500

    Fix ATA SMART and CHECK POWER MODE
    
    This patch fixes two things:
    
     1) CHECK POWER MODE
    
    The error return value wasn't always zero, so it would show up as
    offline.  Error is now explicitly set to zero.
    
     2) SMART
    
    The smart values that were returned were invalid and tools like skdump
    would not recognize that the smart data was actually valid and would
    dump weird output.  The data has been fixed up and raw value support
    was added.  Tools like skdump and palimpsest work as expected.
    
    Signed-off-by: Brian Wheeler <bdwheele at indiana.edu>
    Acked-by: Ryan Harper <ryanh at us.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 9c91a49..1ffca56 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -34,13 +34,26 @@
 
 #include <hw/ide/internal.h>
 
-static const int smart_attributes[][5] = {
-    /* id,  flags, val, wrst, thrsh */
-    { 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
-    { 0x03, 0x03, 0x64, 0x64, 0x46}, /* spin up */
-    { 0x04, 0x02, 0x64, 0x64, 0x14}, /* start stop count */
-    { 0x05, 0x03, 0x64, 0x64, 0x36}, /* remapped sectors */
-    { 0x00, 0x00, 0x00, 0x00, 0x00}
+/* These values were based on a Seagate ST3500418AS but have been modified
+   to make more sense in QEMU */
+static const int smart_attributes[][12] = {
+    /* id,  flags, hflags, val, wrst, raw (6 bytes), threshold */
+    /* raw read error rate*/
+    { 0x01, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06},
+    /* spin up */
+    { 0x03, 0x03, 0x00, 0x64, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+    /* start stop count */
+    { 0x04, 0x02, 0x00, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14},
+    /* remapped sectors */
+    { 0x05, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24},
+    /* power on hours */
+    { 0x09, 0x03, 0x00, 0x64, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+    /* power cycle count */
+    { 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+    /* airflow-temperature-celsius */
+    { 190,  0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
+    /* end of list */
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 };
 
 /* XXX: DVDs that could fit on a CD will be reported as a CD */
@@ -1843,6 +1856,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         break;
     case WIN_CHECKPOWERMODE1:
     case WIN_CHECKPOWERMODE2:
+        s->error = 0;
         s->nsector = 0xff; /* device active or idle */
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s->bus);
@@ -2097,7 +2111,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 		if (smart_attributes[n][0] == 0)
 			break;
 		s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
-		s->io_buffer[2+1+(n*12)] = smart_attributes[n][4];
+		s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];
 		}
 		for (n=0; n<511; n++) /* checksum */
 		s->io_buffer[511] += s->io_buffer[n];
@@ -2110,12 +2124,13 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 		memset(s->io_buffer, 0, 0x200);
 		s->io_buffer[0] = 0x01; /* smart struct version */
 		for (n=0; n<30; n++) {
-		if (smart_attributes[n][0] == 0)
+		    if (smart_attributes[n][0] == 0) {
 			break;
-		s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
-		s->io_buffer[2+1+(n*12)] = smart_attributes[n][1];
-		s->io_buffer[2+3+(n*12)] = smart_attributes[n][2];
-		s->io_buffer[2+4+(n*12)] = smart_attributes[n][3];
+		    }
+		    int i;
+		    for(i = 0; i < 11; i++) {
+			s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];
+		    }
 		}
 		s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
 		if (s->smart_selftest_count == 0) {
commit 301db7c2dd769d48e97c9a766520f8affff76cd7
Author: Ryan Harper <ryanh at us.ibm.com>
Date:   Mon Mar 7 10:01:04 2011 -0600

    Don't allow multiwrites against a block device without underlying medium
    
    If the block device has been closed, we no longer have a medium to submit
    IO against, check for this before submitting io.  This prevents a segfault
    further in the code where we dereference elements of the block driver.
    
    Signed-off-by: Ryan Harper <ryanh at us.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 0559d83..c8e2f97 100644
--- a/block.c
+++ b/block.c
@@ -2398,6 +2398,14 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     MultiwriteCB *mcb;
     int i;
 
+    /* don't submit writes if we don't have a medium */
+    if (bs->drv == NULL) {
+        for (i = 0; i < num_reqs; i++) {
+            reqs[i].error = -ENOMEDIUM;
+        }
+        return -1;
+    }
+
     if (num_reqs == 0) {
         return 0;
     }
commit 4e59b545868a5ee5f59b346337f0c44209929334
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Feb 22 18:42:31 2011 +0100

    tools: Use real async.c instead of stubs
    
    It's wrong to call BHs directly, even in tools. The only operations that
    schedule BHs are called in a loop that (indirectly) contains a call to
    qemu_bh_poll anyway, so we're not losing the scheduled BHs: Tools either use
    synchronous functions, which are guaranteed to have completed (including any
    BHs) when they return; or if they use asynchronous functions, they need to call
    qemu_aio_wait() or similar functions already today.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index a52f42f..167ccc2 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,7 +13,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
-block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
+block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o
 block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
@@ -63,7 +63,7 @@ common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
-common-obj-y += readline.o console.o cursor.o async.o qemu-error.o
+common-obj-y += readline.o console.o cursor.o qemu-error.o
 common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
diff --git a/qemu-tool.c b/qemu-tool.c
index 392e1c9..d45840d 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -56,53 +56,10 @@ void monitor_print_filename(Monitor *mon, const char *filename)
 {
 }
 
-void async_context_push(void)
-{
-}
-
-void async_context_pop(void)
-{
-}
-
-int get_async_context_id(void)
-{
-    return 0;
-}
-
 void monitor_protocol_event(MonitorEvent event, QObject *data)
 {
 }
 
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
-{
-    QEMUBH *bh;
-
-    bh = qemu_malloc(sizeof(*bh));
-    bh->cb = cb;
-    bh->opaque = opaque;
-
-    return bh;
-}
-
-int qemu_bh_poll(void)
-{
-    return 0;
-}
-
-void qemu_bh_schedule(QEMUBH *bh)
-{
-    bh->cb(bh->opaque);
-}
-
-void qemu_bh_cancel(QEMUBH *bh)
-{
-}
-
-void qemu_bh_delete(QEMUBH *bh)
-{
-    qemu_free(bh);
-}
-
 int qemu_set_fd_handler2(int fd,
                          IOCanReadHandler *fd_read_poll,
                          IOHandler *fd_read,
@@ -111,3 +68,7 @@ int qemu_set_fd_handler2(int fd,
 {
     return 0;
 }
+
+void qemu_notify_event(void)
+{
+}
commit e11480db7ff15a9e878f6b3cc1199b439bf7c825
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 1 10:48:12 2011 +0100

    Add error message for loading snapshot without VM state
    
    It already fails, but it didn't tell the user why.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 60d2f2a..d1b9b4a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2021,6 +2021,8 @@ int load_vmstate(const char *name)
     if (ret < 0) {
         return ret;
     } else if (sn.vm_state_size == 0) {
+        error_report("This is a disk-only snapshot. Revert to it offline "
+            "using qemu-img.");
         return -EINVAL;
     }
 
commit 5614c188c65a8194ae499cb16400cab690a45299
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Feb 19 22:18:12 2011 +0100

    block/qcow: Don't ignore immediate read/write and other failures
    
    This patch is similar to 171e3d6b9997c98a97d0c525867f7cd9b640cadd
    which fixed qcow2:
    
    Returning -EIO is far from optimal, but at least it's an error code.
    
    In addition to read/write failures, -EIO is also returned when
    decompress_cluster failed.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow.c b/block/qcow.c
index f67d3d3..a26c886 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -589,8 +589,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
             acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
                 &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
-            if (acb->hd_aiocb == NULL)
+            if (acb->hd_aiocb == NULL) {
+                ret = -EIO;
                 goto done;
+            }
         } else {
             /* Note: in this case, no need to wait */
             memset(acb->buf, 0, 512 * acb->n);
@@ -598,8 +600,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (decompress_cluster(bs, acb->cluster_offset) < 0)
+        if (decompress_cluster(bs, acb->cluster_offset) < 0) {
+            ret = -EIO;
             goto done;
+        }
         memcpy(acb->buf,
                s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
         goto redo;
@@ -614,8 +618,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_aiocb = bdrv_aio_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
-        if (acb->hd_aiocb == NULL)
+        if (acb->hd_aiocb == NULL) {
+            ret = -EIO;
             goto done;
+        }
     }
 
     return;
@@ -700,8 +706,10 @@ static void qcow_aio_write_cb(void *opaque, int ret)
                                     (cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->n,
                                     qcow_aio_write_cb, acb);
-    if (acb->hd_aiocb == NULL)
+    if (acb->hd_aiocb == NULL) {
+        ret = -EIO;
         goto done;
+    }
     return;
 
 done:
commit 40a892b78c9a620bc5ace4164dd566764c35cb53
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Feb 19 22:18:11 2011 +0100

    block/vdi: Don't ignore immediate read/write failures
    
    This patch is similar to 171e3d6b9997c98a97d0c525867f7cd9b640cadd
    which fixed qcow2:
    
    Returning -EIO is far from optimal, but at least it's an error code.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 116b25b..9054079 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -610,6 +610,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
         acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
                                        n_sectors, vdi_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL) {
+            ret = -EIO;
             goto done;
         }
     }
@@ -673,6 +674,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
                                             vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
+                ret = -EIO;
                 goto done;
             }
             return;
@@ -702,6 +704,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                             n_sectors, vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
+                ret = -EIO;
                 goto done;
             }
             return;
@@ -752,6 +755,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
                                         &acb->hd_qiov, s->block_sectors,
                                         vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
+            ret = -EIO;
             goto done;
         }
     } else {
@@ -764,6 +768,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                         n_sectors, vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
+            ret = -EIO;
             goto done;
         }
     }
commit 3c85e74fbf9e5a39d8d13ef91a5f3dd91f0bc8a8
Author: Huang Ying <ying.huang at intel.com>
Date:   Wed Mar 2 08:56:20 2011 +0100

    KVM, MCE, unpoison memory address across reboot
    
    In Linux kernel HWPoison processing implementation, the virtual
    address in processes mapping the error physical memory page is marked
    as HWPoison.  So that, the further accessing to the virtual
    address will kill corresponding processes with SIGBUS.
    
    If the error physical memory page is used by a KVM guest, the SIGBUS
    will be sent to QEMU, and QEMU will simulate a MCE to report that
    memory error to the guest OS.  If the guest OS can not recover from
    the error (for example, the page is accessed by kernel code), guest OS
    will reboot the system.  But because the underlying host virtual
    address backing the guest physical memory is still poisoned, if the
    guest system accesses the corresponding guest physical memory even
    after rebooting, the SIGBUS will still be sent to QEMU and MCE will be
    simulated.  That is, guest system can not recover via rebooting.
    
    In fact, across rebooting, the contents of guest physical memory page
    need not to be kept.  We can allocate a new host physical page to
    back the corresponding guest physical address.
    
    This patch fixes this issue in QEMU-KVM via calling qemu_ram_remap()
    to clear the corresponding page table entry, so that make it possible
    to allocate a new page to recover the issue.
    
    [ Jan: rebasing and tiny cleanups]
    
    Signed-off-by: Huang Ying <ying.huang at intel.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 1574186..f7995bd 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -173,7 +173,40 @@ static int get_para_features(CPUState *env)
 }
 #endif /* CONFIG_KVM_PARA */
 
+typedef struct HWPoisonPage {
+    ram_addr_t ram_addr;
+    QLIST_ENTRY(HWPoisonPage) list;
+} HWPoisonPage;
+
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
+    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
+
+static void kvm_unpoison_all(void *param)
+{
+    HWPoisonPage *page, *next_page;
+
+    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
+        QLIST_REMOVE(page, list);
+        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
+        qemu_free(page);
+    }
+}
+
 #ifdef KVM_CAP_MCE
+static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
+{
+    HWPoisonPage *page;
+
+    QLIST_FOREACH(page, &hwpoison_page_list, list) {
+        if (page->ram_addr == ram_addr) {
+            return;
+        }
+    }
+    page = qemu_malloc(sizeof(HWPoisonPage));
+    page->ram_addr = ram_addr;
+    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
+}
+
 static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
                                      int *max_banks)
 {
@@ -233,6 +266,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
                 hardware_memory_error();
             }
         }
+        kvm_hwpoison_page_add(ram_addr);
         kvm_mce_inject(env, paddr, code);
     } else
 #endif /* KVM_CAP_MCE */
@@ -263,6 +297,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
                     "QEMU itself instead of guest system!: %p\n", addr);
             return 0;
         }
+        kvm_hwpoison_page_add(ram_addr);
         kvm_mce_inject(first_cpu, paddr, code);
     } else
 #endif /* KVM_CAP_MCE */
@@ -571,6 +606,7 @@ int kvm_arch_init(KVMState *s)
         fprintf(stderr, "e820_add_entry() table is full\n");
         return ret;
     }
+    qemu_register_reset(kvm_unpoison_all, NULL);
 
     return 0;
 }
commit cd19cfa23609dc1a35dd34f0b7554a8462337fde
Author: Huang Ying <ying.huang at intel.com>
Date:   Wed Mar 2 08:56:19 2011 +0100

    Add qemu_ram_remap
    
    qemu_ram_remap() unmaps the specified RAM pages, then re-maps these
    pages again.  This is used by KVM HWPoison support to clear HWPoisoned
    page tables across guest rebooting, so that a new page may be
    allocated later to recover the memory error.
    
    [ Jan: style fixlets, WIN32 fix ]
    
    Signed-off-by: Huang Ying <ying.huang at intel.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index caf5e6c..4f4631d 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -863,10 +863,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
 extern int phys_ram_fd;
 extern ram_addr_t ram_size;
 
+/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
+#define RAM_PREALLOC_MASK   (1 << 0)
+
 typedef struct RAMBlock {
     uint8_t *host;
     ram_addr_t offset;
     ram_addr_t length;
+    uint32_t flags;
     char idstr[256];
     QLIST_ENTRY(RAMBlock) next;
 #if defined(__linux__) && !defined(TARGET_S390X)
diff --git a/cpu-common.h b/cpu-common.h
index 54d21d4..ef4e8da 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -50,6 +50,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
                         ram_addr_t size, void *host);
 ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
+void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
 /* Same but slower, to use for migration, where the order of
diff --git a/exec.c b/exec.c
index 3d78063..723ace4 100644
--- a/exec.c
+++ b/exec.c
@@ -2867,6 +2867,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
 
     if (host) {
         new_block->host = host;
+        new_block->flags |= RAM_PREALLOC_MASK;
     } else {
         if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
@@ -2920,7 +2921,9 @@ void qemu_ram_free(ram_addr_t addr)
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (addr == block->offset) {
             QLIST_REMOVE(block, next);
-            if (mem_path) {
+            if (block->flags & RAM_PREALLOC_MASK) {
+                ;
+            } else if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
                 if (block->fd) {
                     munmap(block->host, block->length);
@@ -2943,6 +2946,64 @@ void qemu_ram_free(ram_addr_t addr)
 
 }
 
+#ifndef _WIN32
+void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
+{
+    RAMBlock *block;
+    ram_addr_t offset;
+    int flags;
+    void *area, *vaddr;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        offset = addr - block->offset;
+        if (offset < block->length) {
+            vaddr = block->host + offset;
+            if (block->flags & RAM_PREALLOC_MASK) {
+                ;
+            } else {
+                flags = MAP_FIXED;
+                munmap(vaddr, length);
+                if (mem_path) {
+#if defined(__linux__) && !defined(TARGET_S390X)
+                    if (block->fd) {
+#ifdef MAP_POPULATE
+                        flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
+                            MAP_PRIVATE;
+#else
+                        flags |= MAP_PRIVATE;
+#endif
+                        area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
+                                    flags, block->fd, offset);
+                    } else {
+                        flags |= MAP_PRIVATE | MAP_ANONYMOUS;
+                        area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
+                                    flags, -1, 0);
+                    }
+#endif
+                } else {
+#if defined(TARGET_S390X) && defined(CONFIG_KVM)
+                    flags |= MAP_SHARED | MAP_ANONYMOUS;
+                    area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
+                                flags, -1, 0);
+#else
+                    flags |= MAP_PRIVATE | MAP_ANONYMOUS;
+                    area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
+                                flags, -1, 0);
+#endif
+                }
+                if (area != vaddr) {
+                    fprintf(stderr, "Could not remap addr: %lx@%lx\n",
+                            length, addr);
+                    exit(1);
+                }
+                qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
+            }
+            return;
+        }
+    }
+}
+#endif /* !_WIN32 */
+
 /* Return a host pointer to ram allocated with qemu_ram_alloc.
    With the exception of the softmmu code in this file, this should
    only be used for local memory (e.g. video ram) that the device owns,
commit 75d49497332361a574d9ed1f546d36de385d238f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:18 2011 +0100

    kvm: x86: Fail kvm_arch_init_vcpu if MCE initialization fails
    
    There is no reason to continue if the kernel claims to support MCE but
    then fails to process our request.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9d71b20..1574186 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -437,20 +437,24 @@ int kvm_arch_init_vcpu(CPUState *env)
         int banks;
         int ret;
 
-        if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks)) {
-            perror("kvm_get_mce_cap_supported FAILED");
-        } else {
-            if (banks > MCE_BANKS_DEF)
-                banks = MCE_BANKS_DEF;
-            mcg_cap &= MCE_CAP_DEF;
-            mcg_cap |= banks;
-            ret = kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap);
-            if (ret < 0) {
-                fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
-            } else {
-                env->mcg_cap = mcg_cap;
-            }
+        ret = kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks);
+        if (ret < 0) {
+            fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret));
+            return ret;
         }
+
+        if (banks > MCE_BANKS_DEF) {
+            banks = MCE_BANKS_DEF;
+        }
+        mcg_cap &= MCE_CAP_DEF;
+        mcg_cap |= banks;
+        ret = kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap);
+        if (ret < 0) {
+            fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
+            return ret;
+        }
+
+        env->mcg_cap = mcg_cap;
     }
 #endif
 
commit 32a420243cd1d6d83bd3a248eebeb9a5ebb5101e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:17 2011 +0100

    kvm: x86: Clean up kvm_setup_mce
    
    There is nothing to abstract here. Fold kvm_setup_mce into its caller
    and fix up the error reporting (return code of kvm_vcpu_ioctl holds the
    error value).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 4974fa4..9d71b20 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -187,11 +187,6 @@ static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
     return -ENOSYS;
 }
 
-static int kvm_setup_mce(CPUState *env, uint64_t *mcg_cap)
-{
-    return kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, mcg_cap);
-}
-
 static void kvm_mce_inject(CPUState *env, target_phys_addr_t paddr, int code)
 {
     uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
@@ -440,6 +435,7 @@ int kvm_arch_init_vcpu(CPUState *env)
         && kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) {
         uint64_t mcg_cap;
         int banks;
+        int ret;
 
         if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks)) {
             perror("kvm_get_mce_cap_supported FAILED");
@@ -448,8 +444,9 @@ int kvm_arch_init_vcpu(CPUState *env)
                 banks = MCE_BANKS_DEF;
             mcg_cap &= MCE_CAP_DEF;
             mcg_cap |= banks;
-            if (kvm_setup_mce(env, &mcg_cap)) {
-                perror("kvm_setup_mce FAILED");
+            ret = kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap);
+            if (ret < 0) {
+                fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
             } else {
                 env->mcg_cap = mcg_cap;
             }
commit c34d440a728fd3b5099d11dec122d440ef092c23
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:16 2011 +0100

    kvm: x86: Consolidate TCG and KVM MCE injection code
    
    This switches KVM's MCE injection path to cpu_x86_inject_mce, both for
    SIGBUS and monitor initiated events. This means we prepare the MCA MSRs
    in the VCPUState also for KVM.
    
    We have to drop the MSRs writeback restrictions for this purpose which
    is now safe as every uncoordinated MSR injection is removed with this
    patch.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index a32960c..a08309f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -27,7 +27,6 @@
 #include "exec-all.h"
 #include "qemu-common.h"
 #include "kvm.h"
-#include "kvm_x86.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu.h"
 #include "monitor.h"
@@ -1167,7 +1166,6 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
     };
     unsigned bank_num = cenv->mcg_cap & 0xff;
     CPUState *env;
-    int flag = 0;
 
     if (!cenv->mcg_cap) {
         monitor_printf(mon, "MCE injection not supported\n");
@@ -1187,27 +1185,19 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
         return;
     }
 
-    if (kvm_enabled()) {
-        if (flags & MCE_INJECT_BROADCAST) {
-            flag |= MCE_BROADCAST;
-        }
-
-        kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
-    } else {
-        run_on_cpu(cenv, do_inject_x86_mce, &params);
-        if (flags & MCE_INJECT_BROADCAST) {
-            params.bank = 1;
-            params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
-            params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
-            params.addr = 0;
-            params.misc = 0;
-            for (env = first_cpu; env != NULL; env = env->next_cpu) {
-                if (cenv == env) {
-                    continue;
-                }
-                params.env = env;
-                run_on_cpu(cenv, do_inject_x86_mce, &params);
+    run_on_cpu(cenv, do_inject_x86_mce, &params);
+    if (flags & MCE_INJECT_BROADCAST) {
+        params.bank = 1;
+        params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
+        params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
+        params.addr = 0;
+        params.misc = 0;
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            if (cenv == env) {
+                continue;
             }
+            params.env = env;
+            run_on_cpu(cenv, do_inject_x86_mce, &params);
         }
     }
 }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index d9a6fc5..4974fa4 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -28,7 +28,6 @@
 #include "hw/pc.h"
 #include "hw/apic.h"
 #include "ioport.h"
-#include "kvm_x86.h"
 
 #ifdef CONFIG_KVM_PARA
 #include <linux/kvm_para.h>
@@ -193,164 +192,23 @@ static int kvm_setup_mce(CPUState *env, uint64_t *mcg_cap)
     return kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, mcg_cap);
 }
 
-static int kvm_set_mce(CPUState *env, struct kvm_x86_mce *m)
+static void kvm_mce_inject(CPUState *env, target_phys_addr_t paddr, int code)
 {
-    return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, m);
-}
-
-static int kvm_get_msr(CPUState *env, struct kvm_msr_entry *msrs, int n)
-{
-    struct kvm_msrs *kmsrs = qemu_malloc(sizeof *kmsrs + n * sizeof *msrs);
-    int r;
-
-    kmsrs->nmsrs = n;
-    memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
-    r = kvm_vcpu_ioctl(env, KVM_GET_MSRS, kmsrs);
-    memcpy(msrs, kmsrs->entries, n * sizeof *msrs);
-    free(kmsrs);
-    return r;
-}
-
-/* FIXME: kill this and kvm_get_msr, use env->mcg_status instead */
-static int kvm_mce_in_progress(CPUState *env)
-{
-    struct kvm_msr_entry msr_mcg_status = {
-        .index = MSR_MCG_STATUS,
-    };
-    int r;
-
-    r = kvm_get_msr(env, &msr_mcg_status, 1);
-    if (r == -1 || r == 0) {
-        fprintf(stderr, "Failed to get MCE status\n");
-        return 0;
-    }
-    return !!(msr_mcg_status.data & MCG_STATUS_MCIP);
-}
-
-struct kvm_x86_mce_data
-{
-    CPUState *env;
-    struct kvm_x86_mce *mce;
-    int abort_on_error;
-};
-
-static void kvm_do_inject_x86_mce(void *_data)
-{
-    struct kvm_x86_mce_data *data = _data;
-    int r;
-
-    /* If there is an MCE exception being processed, ignore this SRAO MCE */
-    if ((data->env->mcg_cap & MCG_SER_P) &&
-        !(data->mce->status & MCI_STATUS_AR)) {
-        if (kvm_mce_in_progress(data->env)) {
-            return;
-        }
-    }
-
-    r = kvm_set_mce(data->env, data->mce);
-    if (r < 0) {
-        perror("kvm_set_mce FAILED");
-        if (data->abort_on_error) {
-            abort();
-        }
-    }
-}
-
-static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce,
-                                  int flag)
-{
-    struct kvm_x86_mce_data data = {
-        .env = env,
-        .mce = mce,
-        .abort_on_error = (flag & ABORT_ON_ERROR),
-    };
-
-    if (!env->mcg_cap) {
-        fprintf(stderr, "MCE support is not enabled!\n");
-        return;
-    }
-
-    run_on_cpu(env, kvm_do_inject_x86_mce, &data);
-}
+    uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
+                      MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S;
+    uint64_t mcg_status = MCG_STATUS_MCIP;
 
-static void kvm_mce_broadcast_rest(CPUState *env)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 1,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = 0,
-        .misc = 0,
-    };
-    CPUState *cenv;
-
-    /* Broadcast MCA signal for processor version 06H_EH and above */
-    if (cpu_x86_support_mca_broadcast(env)) {
-        for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
-            if (cenv == env) {
-                continue;
-            }
-            kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
-        }
-    }
-}
-
-static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | MCI_STATUS_AR | 0x134,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-    int r;
-
-    r = kvm_set_mce(env, &mce);
-    if (r < 0) {
-        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
-        abort();
-    }
-    kvm_mce_broadcast_rest(env);
-}
-
-static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | 0xc0,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-    int r;
-
-    r = kvm_set_mce(env, &mce);
-    if (r < 0) {
-        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
-        abort();
+    if (code == BUS_MCEERR_AR) {
+        status |= MCI_STATUS_AR | 0x134;
+        mcg_status |= MCG_STATUS_EIPV;
+    } else {
+        status |= 0xc0;
+        mcg_status |= MCG_STATUS_RIPV;
     }
-    kvm_mce_broadcast_rest(env);
-}
-
-static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | 0xc0,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-
-    kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
-    kvm_mce_broadcast_rest(env);
+    cpu_x86_inject_mce(NULL, env, 9, status, mcg_status, paddr,
+                       (MCM_ADDR_PHYS << 6) | 0xc,
+                       cpu_x86_support_mca_broadcast(env) ?
+                       MCE_INJECT_BROADCAST : 0);
 }
 #endif /* KVM_CAP_MCE */
 
@@ -363,16 +221,14 @@ static void hardware_memory_error(void)
 int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
 {
 #ifdef KVM_CAP_MCE
-    void *vaddr;
     ram_addr_t ram_addr;
     target_phys_addr_t paddr;
 
     if ((env->mcg_cap & MCG_SER_P) && addr
-        && (code == BUS_MCEERR_AR
-            || code == BUS_MCEERR_AO)) {
-        vaddr = (void *)addr;
-        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
-            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
+        && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
+        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
+            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr,
+                                               &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!\n");
             /* Hope we are lucky for AO MCE */
@@ -382,20 +238,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
                 hardware_memory_error();
             }
         }
-
-        if (code == BUS_MCEERR_AR) {
-            /* Fake an Intel architectural Data Load SRAR UCR */
-            kvm_mce_inj_srar_dataload(env, paddr);
-        } else {
-            /*
-             * If there is an MCE excpetion being processed, ignore
-             * this SRAO MCE
-             */
-            if (!kvm_mce_in_progress(env)) {
-                /* Fake an Intel architectural Memory scrubbing UCR */
-                kvm_mce_inj_srao_memscrub(env, paddr);
-            }
-        }
+        kvm_mce_inject(env, paddr, code);
     } else
 #endif /* KVM_CAP_MCE */
     {
@@ -414,20 +257,18 @@ int kvm_arch_on_sigbus(int code, void *addr)
 {
 #ifdef KVM_CAP_MCE
     if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
-        void *vaddr;
         ram_addr_t ram_addr;
         target_phys_addr_t paddr;
 
         /* Hope we are lucky for AO MCE */
-        vaddr = addr;
-        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
+        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
             !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
                                                &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!: %p\n", addr);
             return 0;
         }
-        kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
+        kvm_mce_inject(first_cpu, paddr, code);
     } else
 #endif /* KVM_CAP_MCE */
     {
@@ -442,31 +283,6 @@ int kvm_arch_on_sigbus(int code, void *addr)
     return 0;
 }
 
-void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                        int flag)
-{
-#ifdef KVM_CAP_MCE
-    struct kvm_x86_mce mce = {
-        .bank = bank,
-        .status = status,
-        .mcg_status = mcg_status,
-        .addr = addr,
-        .misc = misc,
-    };
-
-    if (flag & MCE_BROADCAST) {
-        kvm_mce_broadcast_rest(cenv);
-    }
-
-    kvm_inject_x86_mce_on(cenv, &mce, flag);
-#else /* !KVM_CAP_MCE*/
-    if (flag & ABORT_ON_ERROR) {
-        abort();
-    }
-#endif /* !KVM_CAP_MCE*/
-}
-
 static int kvm_inject_mce_oldstyle(CPUState *env)
 {
 #ifdef KVM_CAP_MCE
@@ -1053,14 +869,10 @@ static int kvm_put_msrs(CPUState *env, int level)
     if (env->mcg_cap) {
         int i;
 
-        if (level == KVM_PUT_RESET_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-        } else if (level == KVM_PUT_FULL_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
-            for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
-                kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
-            }
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
+        for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
+            kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
         }
     }
 #endif
diff --git a/target-i386/kvm_x86.h b/target-i386/kvm_x86.h
deleted file mode 100644
index 9d7b584..0000000
--- a/target-i386/kvm_x86.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * QEMU KVM support
- *
- * Copyright (C) 2009 Red Hat Inc.
- * Copyright IBM, Corp. 2008
- *
- * Authors:
- *  Anthony Liguori   <aliguori at us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef __KVM_X86_H__
-#define __KVM_X86_H__
-
-#define ABORT_ON_ERROR  0x01
-#define MCE_BROADCAST   0x02
-
-void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                        int flag);
-
-#endif
commit d5bfda334adf9af62df5709cdac38f523f815f47
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:15 2011 +0100

    x86: Run qemu_inject_x86_mce on target VCPU
    
    We will use the current TCG-only MCE injection path for KVM as well, and
    then this read-modify-write of the target VCPU state has to be performed
    synchronously in the corresponding thread.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index e3ef40c..a32960c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1067,29 +1067,42 @@ static void breakpoint_handler(CPUState *env)
         prev_debug_excp_handler(env);
 }
 
-static void
-qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
-                    uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                    int flags)
+typedef struct MCEInjectionParams {
+    Monitor *mon;
+    CPUState *env;
+    int bank;
+    uint64_t status;
+    uint64_t mcg_status;
+    uint64_t addr;
+    uint64_t misc;
+    int flags;
+} MCEInjectionParams;
+
+static void do_inject_x86_mce(void *data)
 {
-    uint64_t mcg_cap = cenv->mcg_cap;
-    uint64_t *banks = cenv->mce_banks + 4 * bank;
+    MCEInjectionParams *params = data;
+    CPUState *cenv = params->env;
+    uint64_t *banks = cenv->mce_banks + 4 * params->bank;
+
+    cpu_synchronize_state(cenv);
 
     /*
      * If there is an MCE exception being processed, ignore this SRAO MCE
      * unless unconditional injection was requested.
      */
-    if (!(flags & MCE_INJECT_UNCOND_AO) && !(status & MCI_STATUS_AR)
+    if (!(params->flags & MCE_INJECT_UNCOND_AO)
+        && !(params->status & MCI_STATUS_AR)
         && (cenv->mcg_status & MCG_STATUS_MCIP)) {
         return;
     }
-    if (status & MCI_STATUS_UC) {
+
+    if (params->status & MCI_STATUS_UC) {
         /*
          * if MSR_MCG_CTL is not all 1s, the uncorrected error
          * reporting is disabled
          */
-        if ((mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
-            monitor_printf(mon,
+        if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
+            monitor_printf(params->mon,
                            "CPU %d: Uncorrected error reporting disabled\n",
                            cenv->cpu_index);
             return;
@@ -1100,35 +1113,39 @@ qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
          * reporting is disabled for the bank
          */
         if (banks[0] != ~(uint64_t)0) {
-            monitor_printf(mon, "CPU %d: Uncorrected error reporting disabled "
-                           "for bank %d\n", cenv->cpu_index, bank);
+            monitor_printf(params->mon,
+                           "CPU %d: Uncorrected error reporting disabled for"
+                           " bank %d\n",
+                           cenv->cpu_index, params->bank);
             return;
         }
 
         if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
             !(cenv->cr[4] & CR4_MCE_MASK)) {
-            monitor_printf(mon, "CPU %d: Previous MCE still in progress, "
-                                "raising triple fault\n", cenv->cpu_index);
+            monitor_printf(params->mon,
+                           "CPU %d: Previous MCE still in progress, raising"
+                           " triple fault\n",
+                           cenv->cpu_index);
             qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
             qemu_system_reset_request();
             return;
         }
         if (banks[1] & MCI_STATUS_VAL) {
-            status |= MCI_STATUS_OVER;
+            params->status |= MCI_STATUS_OVER;
         }
-        banks[2] = addr;
-        banks[3] = misc;
-        cenv->mcg_status = mcg_status;
-        banks[1] = status;
+        banks[2] = params->addr;
+        banks[3] = params->misc;
+        cenv->mcg_status = params->mcg_status;
+        banks[1] = params->status;
         cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
     } else if (!(banks[1] & MCI_STATUS_VAL)
                || !(banks[1] & MCI_STATUS_UC)) {
         if (banks[1] & MCI_STATUS_VAL) {
-            status |= MCI_STATUS_OVER;
+            params->status |= MCI_STATUS_OVER;
         }
-        banks[2] = addr;
-        banks[3] = misc;
-        banks[1] = status;
+        banks[2] = params->addr;
+        banks[3] = params->misc;
+        banks[1] = params->status;
     } else {
         banks[1] |= MCI_STATUS_OVER;
     }
@@ -1138,6 +1155,16 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
                         uint64_t misc, int flags)
 {
+    MCEInjectionParams params = {
+        .mon = mon,
+        .env = cenv,
+        .bank = bank,
+        .status = status,
+        .mcg_status = mcg_status,
+        .addr = addr,
+        .misc = misc,
+        .flags = flags,
+    };
     unsigned bank_num = cenv->mcg_cap & 0xff;
     CPUState *env;
     int flag = 0;
@@ -1167,17 +1194,19 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
 
         kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
     } else {
-        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc,
-                            flags);
+        run_on_cpu(cenv, do_inject_x86_mce, &params);
         if (flags & MCE_INJECT_BROADCAST) {
+            params.bank = 1;
+            params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
+            params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
+            params.addr = 0;
+            params.misc = 0;
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
                 if (cenv == env) {
                     continue;
                 }
-                qemu_inject_x86_mce(mon, env, 1,
-                                    MCI_STATUS_VAL | MCI_STATUS_UC,
-                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
-                                    flags);
+                params.env = env;
+                run_on_cpu(cenv, do_inject_x86_mce, &params);
             }
         }
     }
commit ab443475c9235822e329e1bfde89be6c71e2c21e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:14 2011 +0100

    kvm: x86: Inject pending MCE events on state writeback
    
    The current way of injecting MCE events without updating of and
    synchronizing with the CPUState is broken and causes spurious
    corruptions of the MCE-related parts of the CPUState.
    
    As a first step towards a fix, enhance the state writeback code with
    support for injecting events that are pending in the CPUState. A pending
    exception will then be signaled via cpu_interrupt(CPU_INTERRUPT_MCE).
    And, just like for TCG, we need to leave the halt state when
    CPU_INTERRUPT_MCE is pending (left broken for the to-be-removed old KVM
    code).
    
    This will also allow to unify TCG and KVM injection code.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0aef810..d9a6fc5 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -467,6 +467,38 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
 #endif /* !KVM_CAP_MCE*/
 }
 
+static int kvm_inject_mce_oldstyle(CPUState *env)
+{
+#ifdef KVM_CAP_MCE
+    if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
+        unsigned int bank, bank_num = env->mcg_cap & 0xff;
+        struct kvm_x86_mce mce;
+
+        env->exception_injected = -1;
+
+        /*
+         * There must be at least one bank in use if an MCE is pending.
+         * Find it and use its values for the event injection.
+         */
+        for (bank = 0; bank < bank_num; bank++) {
+            if (env->mce_banks[bank * 4 + 1] & MCI_STATUS_VAL) {
+                break;
+            }
+        }
+        assert(bank < bank_num);
+
+        mce.bank = bank;
+        mce.status = env->mce_banks[bank * 4 + 1];
+        mce.mcg_status = env->mcg_status;
+        mce.addr = env->mce_banks[bank * 4 + 2];
+        mce.misc = env->mce_banks[bank * 4 + 3];
+
+        return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, &mce);
+    }
+#endif /* KVM_CAP_MCE */
+    return 0;
+}
+
 static void cpu_update_state(void *opaque, int running, int reason)
 {
     CPUState *env = opaque;
@@ -1539,6 +1571,11 @@ int kvm_arch_put_registers(CPUState *env, int level)
     if (ret < 0) {
         return ret;
     }
+    /* must be before kvm_put_msrs */
+    ret = kvm_inject_mce_oldstyle(env);
+    if (ret < 0) {
+        return ret;
+    }
     ret = kvm_put_msrs(env, level);
     if (ret < 0) {
         return ret;
@@ -1677,6 +1714,29 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *env)
 {
+    if (env->interrupt_request & CPU_INTERRUPT_MCE) {
+        /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
+        assert(env->mcg_cap);
+
+        env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+
+        kvm_cpu_synchronize_state(env);
+
+        if (env->exception_injected == EXCP08_DBLE) {
+            /* this means triple fault */
+            qemu_system_reset_request();
+            env->exit_request = 1;
+            return 0;
+        }
+        env->exception_injected = EXCP12_MCHK;
+        env->has_error_code = 0;
+
+        env->halted = 0;
+        if (kvm_irqchip_in_kernel() && env->mp_state == KVM_MP_STATE_HALTED) {
+            env->mp_state = KVM_MP_STATE_RUNNABLE;
+        }
+    }
+
     if (kvm_irqchip_in_kernel()) {
         return 0;
     }
commit 990368650f77d6f2b428b034209331ada7cb463f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:13 2011 +0100

    kvm: Rename kvm_arch_process_irqchip_events to async_events
    
    We will broaden the scope of this function on x86 beyond irqchip events.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 7753c8a..226843c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -893,7 +893,7 @@ int kvm_cpu_exec(CPUState *env)
 
     DPRINTF("kvm_cpu_exec()\n");
 
-    if (kvm_arch_process_irqchip_events(env)) {
+    if (kvm_arch_process_async_events(env)) {
         env->exit_request = 0;
         return EXCP_HLT;
     }
diff --git a/kvm.h b/kvm.h
index 59b2c29..7bc04e0 100644
--- a/kvm.h
+++ b/kvm.h
@@ -102,7 +102,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run);
 
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
 
-int kvm_arch_process_irqchip_events(CPUState *env);
+int kvm_arch_process_async_events(CPUState *env);
 
 int kvm_arch_get_registers(CPUState *env);
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index aba2cc9..0aef810 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1675,7 +1675,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     cpu_set_apic_base(env->apic_state, run->apic_base);
 }
 
-int kvm_arch_process_irqchip_events(CPUState *env)
+int kvm_arch_process_async_events(CPUState *env)
 {
     if (kvm_irqchip_in_kernel()) {
         return 0;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3924f4b..6c99a16 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -259,7 +259,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
 }
 
-int kvm_arch_process_irqchip_events(CPUState *env)
+int kvm_arch_process_async_events(CPUState *env)
 {
     return 0;
 }
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 6e94274..a85ae0f 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -177,7 +177,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
 }
 
-int kvm_arch_process_irqchip_events(CPUState *env)
+int kvm_arch_process_async_events(CPUState *env)
 {
     return 0;
 }
commit 419fb20a8eab0376d86790a9907553307b1654c5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:12 2011 +0100

    kvm: x86: Move MCE functions together
    
    Pure function suffling to avoid multiple #ifdef KVM_CAP_MCE sections,
    no functional changes. While at it, annotate some #ifdef sections.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 1f12cbf..aba2cc9 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -172,7 +172,7 @@ static int get_para_features(CPUState *env)
 #endif
     return features;
 }
-#endif
+#endif /* CONFIG_KVM_PARA */
 
 #ifdef KVM_CAP_MCE
 static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
@@ -273,8 +273,174 @@ static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce,
     run_on_cpu(env, kvm_do_inject_x86_mce, &data);
 }
 
-static void kvm_mce_broadcast_rest(CPUState *env);
-#endif
+static void kvm_mce_broadcast_rest(CPUState *env)
+{
+    struct kvm_x86_mce mce = {
+        .bank = 1,
+        .status = MCI_STATUS_VAL | MCI_STATUS_UC,
+        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+        .addr = 0,
+        .misc = 0,
+    };
+    CPUState *cenv;
+
+    /* Broadcast MCA signal for processor version 06H_EH and above */
+    if (cpu_x86_support_mca_broadcast(env)) {
+        for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
+            if (cenv == env) {
+                continue;
+            }
+            kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
+        }
+    }
+}
+
+static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
+{
+    struct kvm_x86_mce mce = {
+        .bank = 9,
+        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+                  | MCI_STATUS_AR | 0x134,
+        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
+        .addr = paddr,
+        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+    };
+    int r;
+
+    r = kvm_set_mce(env, &mce);
+    if (r < 0) {
+        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
+        abort();
+    }
+    kvm_mce_broadcast_rest(env);
+}
+
+static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
+{
+    struct kvm_x86_mce mce = {
+        .bank = 9,
+        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+                  | 0xc0,
+        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+        .addr = paddr,
+        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+    };
+    int r;
+
+    r = kvm_set_mce(env, &mce);
+    if (r < 0) {
+        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
+        abort();
+    }
+    kvm_mce_broadcast_rest(env);
+}
+
+static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
+{
+    struct kvm_x86_mce mce = {
+        .bank = 9,
+        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+                  | 0xc0,
+        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+        .addr = paddr,
+        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+    };
+
+    kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
+    kvm_mce_broadcast_rest(env);
+}
+#endif /* KVM_CAP_MCE */
+
+static void hardware_memory_error(void)
+{
+    fprintf(stderr, "Hardware memory error!\n");
+    exit(1);
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+{
+#ifdef KVM_CAP_MCE
+    void *vaddr;
+    ram_addr_t ram_addr;
+    target_phys_addr_t paddr;
+
+    if ((env->mcg_cap & MCG_SER_P) && addr
+        && (code == BUS_MCEERR_AR
+            || code == BUS_MCEERR_AO)) {
+        vaddr = (void *)addr;
+        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
+            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
+            fprintf(stderr, "Hardware memory error for memory used by "
+                    "QEMU itself instead of guest system!\n");
+            /* Hope we are lucky for AO MCE */
+            if (code == BUS_MCEERR_AO) {
+                return 0;
+            } else {
+                hardware_memory_error();
+            }
+        }
+
+        if (code == BUS_MCEERR_AR) {
+            /* Fake an Intel architectural Data Load SRAR UCR */
+            kvm_mce_inj_srar_dataload(env, paddr);
+        } else {
+            /*
+             * If there is an MCE excpetion being processed, ignore
+             * this SRAO MCE
+             */
+            if (!kvm_mce_in_progress(env)) {
+                /* Fake an Intel architectural Memory scrubbing UCR */
+                kvm_mce_inj_srao_memscrub(env, paddr);
+            }
+        }
+    } else
+#endif /* KVM_CAP_MCE */
+    {
+        if (code == BUS_MCEERR_AO) {
+            return 0;
+        } else if (code == BUS_MCEERR_AR) {
+            hardware_memory_error();
+        } else {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+#ifdef KVM_CAP_MCE
+    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
+        void *vaddr;
+        ram_addr_t ram_addr;
+        target_phys_addr_t paddr;
+
+        /* Hope we are lucky for AO MCE */
+        vaddr = addr;
+        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
+            !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
+                                               &paddr)) {
+            fprintf(stderr, "Hardware memory error for memory used by "
+                    "QEMU itself instead of guest system!: %p\n", addr);
+            return 0;
+        }
+        kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
+    } else
+#endif /* KVM_CAP_MCE */
+    {
+        if (code == BUS_MCEERR_AO) {
+            return 0;
+        } else if (code == BUS_MCEERR_AR) {
+            hardware_memory_error();
+        } else {
+            return 1;
+        }
+    }
+    return 0;
+}
 
 void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
                         uint64_t mcg_status, uint64_t addr, uint64_t misc,
@@ -294,11 +460,11 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
     }
 
     kvm_inject_x86_mce_on(cenv, &mce, flag);
-#else
+#else /* !KVM_CAP_MCE*/
     if (flag & ABORT_ON_ERROR) {
         abort();
     }
-#endif
+#endif /* !KVM_CAP_MCE*/
 }
 
 static void cpu_update_state(void *opaque, int running, int reason)
@@ -1783,173 +1949,3 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env)
     return !(env->cr[0] & CR0_PE_MASK) ||
            ((env->segs[R_CS].selector  & 3) != 3);
 }
-
-static void hardware_memory_error(void)
-{
-    fprintf(stderr, "Hardware memory error!\n");
-    exit(1);
-}
-
-#ifdef KVM_CAP_MCE
-static void kvm_mce_broadcast_rest(CPUState *env)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 1,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = 0,
-        .misc = 0,
-    };
-    CPUState *cenv;
-
-    /* Broadcast MCA signal for processor version 06H_EH and above */
-    if (cpu_x86_support_mca_broadcast(env)) {
-        for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
-            if (cenv == env) {
-                continue;
-            }
-            kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
-        }
-    }
-}
-
-static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | MCI_STATUS_AR | 0x134,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-    int r;
-
-    r = kvm_set_mce(env, &mce);
-    if (r < 0) {
-        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
-        abort();
-    }
-    kvm_mce_broadcast_rest(env);
-}
-
-static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | 0xc0,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-    int r;
-
-    r = kvm_set_mce(env, &mce);
-    if (r < 0) {
-        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
-        abort();
-    }
-    kvm_mce_broadcast_rest(env);
-}
-
-static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
-{
-    struct kvm_x86_mce mce = {
-        .bank = 9,
-        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
-                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
-                  | 0xc0,
-        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
-        .addr = paddr,
-        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
-    };
-
-    kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
-    kvm_mce_broadcast_rest(env);
-}
-
-#endif
-
-int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
-{
-#if defined(KVM_CAP_MCE)
-    void *vaddr;
-    ram_addr_t ram_addr;
-    target_phys_addr_t paddr;
-
-    if ((env->mcg_cap & MCG_SER_P) && addr
-        && (code == BUS_MCEERR_AR
-            || code == BUS_MCEERR_AO)) {
-        vaddr = (void *)addr;
-        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
-            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
-            fprintf(stderr, "Hardware memory error for memory used by "
-                    "QEMU itself instead of guest system!\n");
-            /* Hope we are lucky for AO MCE */
-            if (code == BUS_MCEERR_AO) {
-                return 0;
-            } else {
-                hardware_memory_error();
-            }
-        }
-
-        if (code == BUS_MCEERR_AR) {
-            /* Fake an Intel architectural Data Load SRAR UCR */
-            kvm_mce_inj_srar_dataload(env, paddr);
-        } else {
-            /*
-             * If there is an MCE excpetion being processed, ignore
-             * this SRAO MCE
-             */
-            if (!kvm_mce_in_progress(env)) {
-                /* Fake an Intel architectural Memory scrubbing UCR */
-                kvm_mce_inj_srao_memscrub(env, paddr);
-            }
-        }
-    } else
-#endif
-    {
-        if (code == BUS_MCEERR_AO) {
-            return 0;
-        } else if (code == BUS_MCEERR_AR) {
-            hardware_memory_error();
-        } else {
-            return 1;
-        }
-    }
-    return 0;
-}
-
-int kvm_arch_on_sigbus(int code, void *addr)
-{
-#if defined(KVM_CAP_MCE)
-    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
-        void *vaddr;
-        ram_addr_t ram_addr;
-        target_phys_addr_t paddr;
-
-        /* Hope we are lucky for AO MCE */
-        vaddr = addr;
-        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
-            !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr, &paddr)) {
-            fprintf(stderr, "Hardware memory error for memory used by "
-                    "QEMU itself instead of guest system!: %p\n", addr);
-            return 0;
-        }
-        kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
-    } else
-#endif
-    {
-        if (code == BUS_MCEERR_AO) {
-            return 0;
-        } else if (code == BUS_MCEERR_AR) {
-            hardware_memory_error();
-        } else {
-            return 1;
-        }
-    }
-    return 0;
-}
commit a7ada1510cb380b86c4811aa40fc45c8a7fc0daf
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:11 2011 +0100

    Synchronize VCPU states before reset
    
    This is required to support keeping VCPU states across a system reset.
    If we do not read the current state before the reset,
    cpu_synchronize_all_post_reset may write back incorrect state
    information.
    
    The first user of this will be MCE MSR synchronization which currently
    works around the missing cpu_synchronize_all_states.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/vl.c b/vl.c
index 5e007a7..f4c24d3 100644
--- a/vl.c
+++ b/vl.c
@@ -1450,6 +1450,7 @@ static void main_loop(void)
         }
         if (qemu_reset_requested()) {
             pause_all_vcpus();
+            cpu_synchronize_all_states();
             qemu_system_reset();
             resume_all_vcpus();
         }
commit 747461c76beb1856343d5cd16bb7663ed2ebf3da
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:10 2011 +0100

    x86: Optionally avoid injecting AO MCEs while others are pending
    
    Allow to tell cpu_x86_inject_mce that it should ignore Action Optional
    MCE events when the target VCPU is still processing another one. This
    will be used by KVM soon.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/monitor.c b/monitor.c
index 662df7c..ae20927 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2709,12 +2709,15 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
     uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
     uint64_t addr = qdict_get_int(qdict, "addr");
     uint64_t misc = qdict_get_int(qdict, "misc");
-    int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
+    int flags = MCE_INJECT_UNCOND_AO;
 
+    if (qdict_get_try_bool(qdict, "broadcast", 0)) {
+        flags |= MCE_INJECT_BROADCAST;
+    }
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if (cenv->cpu_index == cpu_index) {
             cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc,
-                               broadcast);
+                               flags);
             break;
         }
     }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 486af1d..d0eae75 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -987,8 +987,11 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 void do_cpu_init(CPUState *env);
 void do_cpu_sipi(CPUState *env);
 
+#define MCE_INJECT_BROADCAST    1
+#define MCE_INJECT_UNCOND_AO    2
+
 void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
-                        uint64_t misc, int broadcast);
+                        uint64_t misc, int flags);
 
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 462d332..e3ef40c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1069,11 +1069,20 @@ static void breakpoint_handler(CPUState *env)
 
 static void
 qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
-                    uint64_t mcg_status, uint64_t addr, uint64_t misc)
+                    uint64_t mcg_status, uint64_t addr, uint64_t misc,
+                    int flags)
 {
     uint64_t mcg_cap = cenv->mcg_cap;
     uint64_t *banks = cenv->mce_banks + 4 * bank;
 
+    /*
+     * If there is an MCE exception being processed, ignore this SRAO MCE
+     * unless unconditional injection was requested.
+     */
+    if (!(flags & MCE_INJECT_UNCOND_AO) && !(status & MCI_STATUS_AR)
+        && (cenv->mcg_status & MCG_STATUS_MCIP)) {
+        return;
+    }
     if (status & MCI_STATUS_UC) {
         /*
          * if MSR_MCG_CTL is not all 1s, the uncorrected error
@@ -1127,7 +1136,7 @@ qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
 
 void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
-                        uint64_t misc, int broadcast)
+                        uint64_t misc, int flags)
 {
     unsigned bank_num = cenv->mcg_cap & 0xff;
     CPUState *env;
@@ -1145,27 +1154,30 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
         monitor_printf(mon, "Invalid MCE status code\n");
         return;
     }
-    if (broadcast && !cpu_x86_support_mca_broadcast(cenv)) {
+    if ((flags & MCE_INJECT_BROADCAST)
+        && !cpu_x86_support_mca_broadcast(cenv)) {
         monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
         return;
     }
 
     if (kvm_enabled()) {
-        if (broadcast) {
+        if (flags & MCE_INJECT_BROADCAST) {
             flag |= MCE_BROADCAST;
         }
 
         kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
     } else {
-        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc);
-        if (broadcast) {
+        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc,
+                            flags);
+        if (flags & MCE_INJECT_BROADCAST) {
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
                 if (cenv == env) {
                     continue;
                 }
                 qemu_inject_x86_mce(mon, env, 1,
                                     MCI_STATUS_VAL | MCI_STATUS_UC,
-                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
+                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
+                                    flags);
             }
         }
     }
commit 316378e4d0214b45cfeaa01609aca4dabb18d78b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:09 2011 +0100

    x86: Refine error reporting of MCE injection services
    
    As this service is used by the human monitor, make sure that errors get
    reported to the right channel, and also raise the verbosity.
    
    This requires to move Monitor typedef in qemu-common.h to resolve the
    include dependency.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/monitor.c b/monitor.c
index 45b0cc2..662df7c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2712,8 +2712,8 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
     int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
 
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
-        if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
-            cpu_x86_inject_mce(cenv, bank, status, mcg_status, addr, misc,
+        if (cenv->cpu_index == cpu_index) {
+            cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc,
                                broadcast);
             break;
         }
diff --git a/qemu-common.h b/qemu-common.h
index 3fe1719..7a96dd1 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -18,6 +18,9 @@ typedef struct QEMUFile QEMUFile;
 typedef struct QEMUBH QEMUBH;
 typedef struct DeviceState DeviceState;
 
+struct Monitor;
+typedef struct Monitor Monitor;
+
 /* we put basic includes here to avoid repeating them in device drivers */
 #include <stdlib.h>
 #include <stdio.h>
@@ -327,9 +330,6 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
 void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
                             size_t skip);
 
-struct Monitor;
-typedef struct Monitor Monitor;
-
 /* Convert a byte between binary and BCD.  */
 static inline uint8_t to_bcd(uint8_t val)
 {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 52bb48e..486af1d 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -987,8 +987,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 void do_cpu_init(CPUState *env);
 void do_cpu_sipi(CPUState *env);
 
-void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                        int broadcast);
+void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
+                        uint64_t status, uint64_t mcg_status, uint64_t addr,
+                        uint64_t misc, int broadcast);
 
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index ba3bed9..462d332 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -30,6 +30,7 @@
 #include "kvm_x86.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu.h"
+#include "monitor.h"
 #endif
 
 //#define DEBUG_MMU
@@ -1067,33 +1068,38 @@ static void breakpoint_handler(CPUState *env)
 }
 
 static void
-qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
+qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
                     uint64_t mcg_status, uint64_t addr, uint64_t misc)
 {
     uint64_t mcg_cap = cenv->mcg_cap;
-    uint64_t *banks = cenv->mce_banks;
-
-    /*
-     * if MSR_MCG_CTL is not all 1s, the uncorrected error
-     * reporting is disabled
-     */
-    if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
-        cenv->mcg_ctl != ~(uint64_t)0) {
-        return;
-    }
-    banks += 4 * bank;
-    /*
-     * if MSR_MCi_CTL is not all 1s, the uncorrected error
-     * reporting is disabled for the bank
-     */
-    if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0) {
-        return;
-    }
+    uint64_t *banks = cenv->mce_banks + 4 * bank;
+
     if (status & MCI_STATUS_UC) {
+        /*
+         * if MSR_MCG_CTL is not all 1s, the uncorrected error
+         * reporting is disabled
+         */
+        if ((mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
+            monitor_printf(mon,
+                           "CPU %d: Uncorrected error reporting disabled\n",
+                           cenv->cpu_index);
+            return;
+        }
+
+        /*
+         * if MSR_MCi_CTL is not all 1s, the uncorrected error
+         * reporting is disabled for the bank
+         */
+        if (banks[0] != ~(uint64_t)0) {
+            monitor_printf(mon, "CPU %d: Uncorrected error reporting disabled "
+                           "for bank %d\n", cenv->cpu_index, bank);
+            return;
+        }
+
         if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
             !(cenv->cr[4] & CR4_MCE_MASK)) {
-            fprintf(stderr, "injects mce exception while previous "
-                    "one is in progress!\n");
+            monitor_printf(mon, "CPU %d: Previous MCE still in progress, "
+                                "raising triple fault\n", cenv->cpu_index);
             qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
             qemu_system_reset_request();
             return;
@@ -1119,23 +1125,29 @@ qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
     }
 }
 
-void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                        int broadcast)
+void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
+                        uint64_t status, uint64_t mcg_status, uint64_t addr,
+                        uint64_t misc, int broadcast)
 {
     unsigned bank_num = cenv->mcg_cap & 0xff;
     CPUState *env;
     int flag = 0;
 
-    if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
+    if (!cenv->mcg_cap) {
+        monitor_printf(mon, "MCE injection not supported\n");
         return;
     }
-
-    if (broadcast) {
-        if (!cpu_x86_support_mca_broadcast(cenv)) {
-            fprintf(stderr, "Current CPU does not support broadcast\n");
-            return;
-        }
+    if (bank >= bank_num) {
+        monitor_printf(mon, "Invalid MCE bank number\n");
+        return;
+    }
+    if (!(status & MCI_STATUS_VAL)) {
+        monitor_printf(mon, "Invalid MCE status code\n");
+        return;
+    }
+    if (broadcast && !cpu_x86_support_mca_broadcast(cenv)) {
+        monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
+        return;
     }
 
     if (kvm_enabled()) {
@@ -1145,13 +1157,14 @@ void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
 
         kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
     } else {
-        qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
+        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc);
         if (broadcast) {
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
                 if (cenv == env) {
                     continue;
                 }
-                qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
+                qemu_inject_x86_mce(mon, env, 1,
+                                    MCI_STATUS_VAL | MCI_STATUS_UC,
                                     MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
             }
         }
commit 2fa11da0c3a6614b15e6007389986a7c2b31ac49
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:08 2011 +0100

    x86: Small cleanups of MCE helpers
    
    Fix some code style issues, use proper headers, and align to cpu_x86
    naming scheme. No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 87b0f86..caf5e6c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -971,8 +971,4 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
-void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
-                        int broadcast);
-
 #endif /* CPU_ALL_H */
diff --git a/monitor.c b/monitor.c
index 22ae3bb..45b0cc2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2713,7 +2713,7 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
 
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
-            cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc,
+            cpu_x86_inject_mce(cenv, bank, status, mcg_status, addr, misc,
                                broadcast);
             break;
         }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 75156e7..52bb48e 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -986,4 +986,9 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 
 void do_cpu_init(CPUState *env);
 void do_cpu_sipi(CPUState *env);
+
+void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
+                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
+                        int broadcast);
+
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index f41416f..ba3bed9 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -28,6 +28,9 @@
 #include "qemu-common.h"
 #include "kvm.h"
 #include "kvm_x86.h"
+#ifndef CONFIG_USER_ONLY
+#include "sysemu.h"
+#endif
 
 //#define DEBUG_MMU
 
@@ -1063,11 +1066,9 @@ static void breakpoint_handler(CPUState *env)
         prev_debug_excp_handler(env);
 }
 
-/* This should come from sysemu.h - if we could include it here... */
-void qemu_system_reset_request(void);
-
-static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
-                        uint64_t mcg_status, uint64_t addr, uint64_t misc)
+static void
+qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
+                    uint64_t mcg_status, uint64_t addr, uint64_t misc)
 {
     uint64_t mcg_cap = cenv->mcg_cap;
     uint64_t *banks = cenv->mce_banks;
@@ -1077,15 +1078,17 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
      * reporting is disabled
      */
     if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
-        cenv->mcg_ctl != ~(uint64_t)0)
+        cenv->mcg_ctl != ~(uint64_t)0) {
         return;
+    }
     banks += 4 * bank;
     /*
      * if MSR_MCi_CTL is not all 1s, the uncorrected error
      * reporting is disabled for the bank
      */
-    if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0)
+    if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0) {
         return;
+    }
     if (status & MCI_STATUS_UC) {
         if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
             !(cenv->cr[4] & CR4_MCE_MASK)) {
@@ -1095,8 +1098,9 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
             qemu_system_reset_request();
             return;
         }
-        if (banks[1] & MCI_STATUS_VAL)
+        if (banks[1] & MCI_STATUS_VAL) {
             status |= MCI_STATUS_OVER;
+        }
         banks[2] = addr;
         banks[3] = misc;
         cenv->mcg_status = mcg_status;
@@ -1104,16 +1108,18 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
         cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
     } else if (!(banks[1] & MCI_STATUS_VAL)
                || !(banks[1] & MCI_STATUS_UC)) {
-        if (banks[1] & MCI_STATUS_VAL)
+        if (banks[1] & MCI_STATUS_VAL) {
             status |= MCI_STATUS_OVER;
+        }
         banks[2] = addr;
         banks[3] = misc;
         banks[1] = status;
-    } else
+    } else {
         banks[1] |= MCI_STATUS_OVER;
+    }
 }
 
-void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
+void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
                         uint64_t mcg_status, uint64_t addr, uint64_t misc,
                         int broadcast)
 {
@@ -1155,15 +1161,16 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
 
 static void mce_init(CPUX86State *cenv)
 {
-    unsigned int bank, bank_num;
+    unsigned int bank;
 
-    if (((cenv->cpuid_version >> 8)&0xf) >= 6
-        && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)) {
+    if (((cenv->cpuid_version >> 8) & 0xf) >= 6
+        && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+            (CPUID_MCE | CPUID_MCA)) {
         cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
         cenv->mcg_ctl = ~(uint64_t)0;
-        bank_num = MCE_BANKS_DEF;
-        for (bank = 0; bank < bank_num; bank++)
-            cenv->mce_banks[bank*4] = ~(uint64_t)0;
+        for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
+            cenv->mce_banks[bank * 4] = ~(uint64_t)0;
+        }
     }
 }
 
commit 185592324ff92f3c7c5edb4d9e96d40a137ecdcd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:07 2011 +0100

    x86: Perform implicit mcg_status reset
    
    Reorder mcg_status in CPUState to achieve automatic clearing on reset.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5f1df8b..75156e7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -687,6 +687,8 @@ typedef struct CPUX86State {
 
     uint64_t pat;
 
+    uint64_t mcg_status;
+
     /* exception/interrupt handling */
     int error_code;
     int exception_is_int;
@@ -741,7 +743,6 @@ typedef struct CPUX86State {
     struct DeviceState *apic_state;
 
     uint64_t mcg_cap;
-    uint64_t mcg_status;
     uint64_t mcg_ctl;
     uint64_t mce_banks[MCE_BANKS_DEF*4];
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index f0c546d..f41416f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -101,8 +101,6 @@ void cpu_reset(CPUX86State *env)
     env->dr[7] = DR7_FIXED_1;
     cpu_breakpoint_remove_all(env, BP_CPU);
     cpu_watchpoint_remove_all(env, BP_CPU);
-
-    env->mcg_status = 0;
 }
 
 void cpu_x86_close(CPUX86State *env)
commit ac098781583bb1ca8369b5bd81fa5fbafa86231c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:06 2011 +0100

    x86: Account for MCE in cpu_has_work
    
    MCEs can be injected asynchronously, so they can also terminate the halt
    state.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 3e7386e..6f9f709 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -293,15 +293,12 @@ static inline void load_eflags(int eflags, int update_mask)
 
 static inline int cpu_has_work(CPUState *env)
 {
-    int work;
-
-    work = (env->interrupt_request & CPU_INTERRUPT_HARD) &&
-           (env->eflags & IF_MASK);
-    work |= env->interrupt_request & CPU_INTERRUPT_NMI;
-    work |= env->interrupt_request & CPU_INTERRUPT_INIT;
-    work |= env->interrupt_request & CPU_INTERRUPT_SIPI;
-
-    return work;
+    return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (env->eflags & IF_MASK)) ||
+           (env->interrupt_request & (CPU_INTERRUPT_NMI |
+                                      CPU_INTERRUPT_INIT |
+                                      CPU_INTERRUPT_SIPI |
+                                      CPU_INTERRUPT_MCE));
 }
 
 /* load efer and update the corresponding hflags. XXX: do consistency
commit fbc1c7e6886290c72e78bac85db8e779d608b38b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:05 2011 +0100

    kvm: Fix build warning when KVM_CAP_SET_GUEST_DEBUG is lacking
    
    Original fix by David Gibson.
    
    CC: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index e6a7de4..7753c8a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -998,7 +998,9 @@ int kvm_cpu_exec(CPUState *env)
     }
     ret = EXCP_INTERRUPT;
 
+#ifdef KVM_CAP_SET_GUEST_DEBUG
 out:
+#endif
     env->exit_request = 0;
     cpu_single_env = NULL;
     return ret;
commit bdcbd3e2fb98407e6b0928a17d1ed61786cb6389
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Mar 2 08:56:04 2011 +0100

    kvm: ppc: Fix breakage of kvm_arch_pre_run/process_irqchip_events
    
    Commit 7a39fe5882 failed to convert the right arch function.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index bd4012a..3924f4b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -222,7 +222,7 @@ int kvmppc_set_interrupt(CPUState *env, int irq, int level)
 #define PPC_INPUT_INT PPC6xx_INPUT_INT
 #endif
 
-int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
     int r;
     unsigned irq;
@@ -253,15 +253,15 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     /* We don't know if there are more interrupts pending after this. However,
      * the guest will return to userspace in the course of handling this one
      * anyways, so we will get a chance to deliver the rest. */
-    return 0;
 }
 
 void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
 }
 
-void kvm_arch_process_irqchip_events(CPUState *env)
+int kvm_arch_process_irqchip_events(CPUState *env)
 {
+    return 0;
 }
 
 static int kvmppc_handle_halt(CPUState *env)
commit cc015e9a5dde2f03f123357fa060acbdfcd570a4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:08 2011 +0100

    add Win32 IPI service
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 7559a02..077729c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -854,13 +854,32 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     return NULL;
 }
 
+static void qemu_cpu_kick_thread(CPUState *env)
+{
+#ifndef _WIN32
+    int err;
+
+    err = pthread_kill(env->thread->thread, SIG_IPI);
+    if (err) {
+        fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
+        exit(1);
+    }
+#else /* _WIN32 */
+    if (!qemu_cpu_is_self(env)) {
+        SuspendThread(env->thread->thread);
+        cpu_signal(0);
+        ResumeThread(env->thread->thread);
+    }
+#endif
+}
+
 void qemu_cpu_kick(void *_env)
 {
     CPUState *env = _env;
 
     qemu_cond_broadcast(env->halt_cond);
     if (!env->thread_kicked) {
-        qemu_thread_signal(env->thread, SIG_IPI);
+        qemu_cpu_kick_thread(env);
         env->thread_kicked = true;
     }
 }
@@ -871,7 +890,7 @@ void qemu_cpu_kick_self(void)
     assert(cpu_single_env);
 
     if (!cpu_single_env->thread_kicked) {
-        qemu_thread_signal(cpu_single_env->thread, SIG_IPI);
+        qemu_cpu_kick_thread(cpu_single_env);
         cpu_single_env->thread_kicked = true;
     }
 #else
@@ -893,7 +912,7 @@ void qemu_mutex_lock_iothread(void)
     } else {
         qemu_mutex_lock(&qemu_fair_mutex);
         if (qemu_mutex_trylock(&qemu_global_mutex)) {
-            qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
+            qemu_cpu_kick_thread(first_cpu);
             qemu_mutex_lock(&qemu_global_mutex);
         }
         qemu_mutex_unlock(&qemu_fair_mutex);
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 8b54cc0..87c1a9f 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -171,15 +171,6 @@ void qemu_thread_create(QemuThread *thread,
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
 }
 
-void qemu_thread_signal(QemuThread *thread, int sig)
-{
-    int err;
-
-    err = pthread_kill(thread->thread, sig);
-    if (err)
-        error_exit(err, __func__);
-}
-
 void qemu_thread_get_self(QemuThread *thread)
 {
     thread->thread = pthread_self();
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index 7af371c..ee4618e 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -14,5 +14,4 @@ struct QemuThread {
     pthread_t thread;
 };
 
-void qemu_thread_signal(QemuThread *thread, int sig);
 #endif
commit b55c22c65b630137a2374ce9f2cfbf71322b7b71
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:07 2011 +0100

    protect qemu_cpu_kick_self for Win32
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index e0bcb5c..7559a02 100644
--- a/cpus.c
+++ b/cpus.c
@@ -867,12 +867,16 @@ void qemu_cpu_kick(void *_env)
 
 void qemu_cpu_kick_self(void)
 {
+#ifndef _WIN32
     assert(cpu_single_env);
 
     if (!cpu_single_env->thread_kicked) {
         qemu_thread_signal(cpu_single_env->thread, SIG_IPI);
         cpu_single_env->thread_kicked = true;
     }
+#else
+    abort();
+#endif
 }
 
 int qemu_cpu_is_self(void *_env)
commit 714bd040906637441fc10a33d1f6553cfef4938a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:06 2011 +0100

    provide dummy signal init functions for win32
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 2b491a9..e0bcb5c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -196,6 +196,16 @@ static void cpu_handle_debug_exception(CPUState *env)
 #endif
 }
 
+#ifdef CONFIG_IOTHREAD
+static void cpu_signal(int sig)
+{
+    if (cpu_single_env) {
+        cpu_exit(cpu_single_env);
+    }
+    exit_request = 1;
+}
+#endif
+
 #ifdef CONFIG_LINUX
 static void sigbus_reraise(void)
 {
@@ -390,6 +400,61 @@ static int qemu_signal_init(void)
     return 0;
 }
 
+static void qemu_kvm_init_cpu_signals(CPUState *env)
+{
+    int r;
+    sigset_t set;
+    struct sigaction sigact;
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = dummy_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+#ifdef CONFIG_IOTHREAD
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
+    sigdelset(&set, SIGBUS);
+    r = kvm_set_signal_mask(env, &set);
+    if (r) {
+        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+        exit(1);
+    }
+#else
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIGIO);
+    sigdelset(&set, SIGALRM);
+#endif
+    sigdelset(&set, SIG_IPI);
+    sigdelset(&set, SIGBUS);
+    r = kvm_set_signal_mask(env, &set);
+    if (r) {
+        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+        exit(1);
+    }
+}
+
+static void qemu_tcg_init_cpu_signals(void)
+{
+#ifdef CONFIG_IOTHREAD
+    sigset_t set;
+    struct sigaction sigact;
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = cpu_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+#endif
+}
+
 static void qemu_kvm_eat_signals(CPUState *env)
 {
     struct timespec ts = { 0, 0 };
@@ -470,39 +535,17 @@ static int qemu_signal_init(void)
     return 0;
 }
 
-#endif /* _WIN32 */
-
-#ifndef CONFIG_IOTHREAD
 static void qemu_kvm_init_cpu_signals(CPUState *env)
 {
-#ifndef _WIN32
-    int r;
-    sigset_t set;
-    struct sigaction sigact;
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = dummy_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIG_IPI);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
+    abort();
+}
 
-    pthread_sigmask(SIG_BLOCK, NULL, &set);
-    sigdelset(&set, SIG_IPI);
-    sigdelset(&set, SIGBUS);
-    sigdelset(&set, SIGIO);
-    sigdelset(&set, SIGALRM);
-    r = kvm_set_signal_mask(env, &set);
-    if (r) {
-        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
-        exit(1);
-    }
-#endif
+static void qemu_tcg_init_cpu_signals(void)
+{
 }
+#endif /* _WIN32 */
 
+#ifndef CONFIG_IOTHREAD
 int qemu_init_main_loop(void)
 {
     int ret;
@@ -536,6 +579,8 @@ void qemu_init_vcpu(void *_env)
             exit(1);
         }
         qemu_kvm_init_cpu_signals(env);
+    } else {
+        qemu_tcg_init_cpu_signals();
     }
 }
 
@@ -616,48 +661,6 @@ static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-static void cpu_signal(int sig)
-{
-    if (cpu_single_env) {
-        cpu_exit(cpu_single_env);
-    }
-    exit_request = 1;
-}
-
-static void qemu_kvm_init_cpu_signals(CPUState *env)
-{
-    int r;
-    sigset_t set;
-    struct sigaction sigact;
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = dummy_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
-
-    pthread_sigmask(SIG_BLOCK, NULL, &set);
-    sigdelset(&set, SIG_IPI);
-    sigdelset(&set, SIGBUS);
-    r = kvm_set_signal_mask(env, &set);
-    if (r) {
-        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
-        exit(1);
-    }
-}
-
-static void qemu_tcg_init_cpu_signals(void)
-{
-    sigset_t set;
-    struct sigaction sigact;
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = cpu_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-}
-
 int qemu_init_main_loop(void)
 {
     int ret;
commit 712ae48084837ae46f71929099e9587cac68fb9e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:05 2011 +0100

    merge all signal initialization with qemu_signalfd_init, rename
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 32e9352..2b491a9 100644
--- a/cpus.c
+++ b/cpus.c
@@ -346,11 +346,37 @@ static void sigfd_handler(void *opaque)
     }
 }
 
-static int qemu_signalfd_init(sigset_t mask)
+static int qemu_signal_init(void)
 {
     int sigfd;
+    sigset_t set;
 
-    sigfd = qemu_signalfd(&mask);
+#ifdef CONFIG_IOTHREAD
+    /* SIGUSR2 used by posix-aio-compat.c */
+    sigemptyset(&set);
+    sigaddset(&set, SIGUSR2);
+    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIG_IPI);
+    sigaddset(&set, SIGBUS);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+#else
+    sigemptyset(&set);
+    sigaddset(&set, SIGBUS);
+    if (kvm_enabled()) {
+        /*
+         * We need to process timer signals synchronously to avoid a race
+         * between exit_request check and KVM vcpu entry.
+         */
+        sigaddset(&set, SIGIO);
+        sigaddset(&set, SIGALRM);
+    }
+#endif
+
+    sigfd = qemu_signalfd(&set);
     if (sigfd == -1) {
         fprintf(stderr, "failed to create signalfd\n");
         return -errno;
@@ -438,6 +464,12 @@ static void qemu_event_increment(void)
 static void qemu_kvm_eat_signals(CPUState *env)
 {
 }
+
+static int qemu_signal_init(void)
+{
+    return 0;
+}
+
 #endif /* _WIN32 */
 
 #ifndef CONFIG_IOTHREAD
@@ -471,39 +503,14 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
 #endif
 }
 
-#ifndef _WIN32
-static sigset_t block_synchronous_signals(void)
-{
-    sigset_t set;
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGBUS);
-    if (kvm_enabled()) {
-        /*
-         * We need to process timer signals synchronously to avoid a race
-         * between exit_request check and KVM vcpu entry.
-         */
-        sigaddset(&set, SIGIO);
-        sigaddset(&set, SIGALRM);
-    }
-
-    return set;
-}
-#endif
-
 int qemu_init_main_loop(void)
 {
-#ifndef _WIN32
-    sigset_t blocked_signals;
     int ret;
 
-    blocked_signals = block_synchronous_signals();
-
-    ret = qemu_signalfd_init(blocked_signals);
+    ret = qemu_signal_init();
     if (ret) {
         return ret;
     }
-#endif
 
     qemu_init_sigbus();
 
@@ -651,35 +658,13 @@ static void qemu_tcg_init_cpu_signals(void)
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 }
 
-static sigset_t block_io_signals(void)
-{
-    sigset_t set;
-
-    /* SIGUSR2 used by posix-aio-compat.c */
-    sigemptyset(&set);
-    sigaddset(&set, SIGUSR2);
-    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIG_IPI);
-    sigaddset(&set, SIGBUS);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    return set;
-}
-
 int qemu_init_main_loop(void)
 {
     int ret;
-    sigset_t blocked_signals;
 
     qemu_init_sigbus();
 
-    blocked_signals = block_io_signals();
-
-    ret = qemu_signalfd_init(blocked_signals);
+    ret = qemu_signal_init();
     if (ret) {
         return ret;
     }
commit 8cf3f22b77df4aa2a21bd93937b800f08b90e69c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:04 2011 +0100

    iothread stops the vcpu thread via IPI
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 4305184..32e9352 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1086,9 +1086,11 @@ bool cpu_exec_all(void)
         qemu_clock_enable(vm_clock,
                           (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
 
+#ifndef CONFIG_IOTHREAD
         if (qemu_alarm_pending()) {
             break;
         }
+#endif
         if (cpu_can_run(env)) {
             if (kvm_enabled()) {
                 r = kvm_cpu_exec(env);
commit 18a857280d7a945c9fd4034dc2722fd8c2dfb946
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:03 2011 +0100

    do not use timedwait on qemu_cpu_cond
    
    Whenever env->created becomes true, qemu_cpu_cond is signaled by
    {kvm,tcg}_cpu_thread_fn.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 8f169ad..4305184 100644
--- a/cpus.c
+++ b/cpus.c
@@ -970,7 +970,7 @@ static void qemu_tcg_init_vcpu(void *_env)
         qemu_cond_init(env->halt_cond);
         qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
         while (env->created == 0) {
-            qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+            qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
         }
         tcg_cpu_thread = env->thread;
         tcg_halt_cond = env->halt_cond;
@@ -987,7 +987,7 @@ static void qemu_kvm_start_vcpu(CPUState *env)
     qemu_cond_init(env->halt_cond);
     qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
     while (env->created == 0) {
-        qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+        qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
     }
 }
 
commit be7d6c57c4598ca9fcb3f6fbe57c13110ebd6c70
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:02 2011 +0100

    do not use timedwait on qemu_pause_cond
    
    all_vcpus_paused can start returning true after penv->stopped changes
    from 0 to 1.  When this is done, qemu_pause_cond is always signaled.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index e367b3b..8f169ad 100644
--- a/cpus.c
+++ b/cpus.c
@@ -938,7 +938,7 @@ void pause_all_vcpus(void)
     }
 
     while (!all_vcpus_paused()) {
-        qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
+        qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
         penv = first_cpu;
         while (penv) {
             qemu_cpu_kick(penv);
commit e009894f088507e245ae6c62aa0761b2afdf1c6b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:01 2011 +0100

    do not use timedwait on qemu_system_cond
    
    qemu_main_loop_start is the only place where qemu_system_ready is set
    to 1.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 4c3837f..e367b3b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -823,7 +823,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
 
     /* and wait for machine initialization */
     while (!qemu_system_ready) {
-        qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+        qemu_cond_wait(&qemu_system_cond, &qemu_global_mutex);
     }
 
     while (1) {
@@ -855,7 +855,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     /* and wait for machine initialization */
     while (!qemu_system_ready) {
-        qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+        qemu_cond_wait(&qemu_system_cond, &qemu_global_mutex);
     }
 
     while (1) {
commit 9705fbb5636fbe36956e6886227e9e871689cf83
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:44:00 2011 +0100

    do not use timedwait on qemu_halt_cond
    
    The following conditions can cause cpu_has_work(env) to become true:
    
    - env->queued_work_first: run_on_cpu is already kicking the VCPU
    
    - env->stop = 1: pause_all_vcpus is already kicking the VCPU
    
    - env->stopped = 0: resume_all_vcpus is already kicking the VCPU
    
    - vm_running = 1: vm_start is calling resume_all_vcpus
    
    - env->halted = 0: see previous patch
    
    - qemu_cpu_has_work(env): when it becomes true, board code should set
      env->halted = 0 too.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 6cfb45b..4c3837f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -771,7 +771,7 @@ static void qemu_tcg_wait_io_event(void)
     CPUState *env;
 
     while (all_cpu_threads_idle()) {
-        qemu_cond_timedwait(tcg_halt_cond, &qemu_global_mutex, 1000);
+        qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
     }
 
     qemu_mutex_unlock(&qemu_global_mutex);
@@ -794,7 +794,7 @@ static void qemu_tcg_wait_io_event(void)
 static void qemu_kvm_wait_io_event(CPUState *env)
 {
     while (cpu_thread_is_idle(env)) {
-        qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+        qemu_cond_wait(env->halt_cond, &qemu_global_mutex);
     }
 
     qemu_kvm_eat_signals(env);
commit 67bb172f9d995880a9c752e9f33819f4a63a3fda
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:59 2011 +0100

    always signal pause_cond after stopping a VCPU
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 785a104..6cfb45b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1012,8 +1012,10 @@ void qemu_notify_event(void)
 void cpu_stop_current(void)
 {
     if (cpu_single_env) {
+        cpu_single_env->stop = 0;
         cpu_single_env->stopped = 1;
         cpu_exit(cpu_single_env);
+        qemu_cond_signal(&qemu_pause_cond);
     }
 }
 
commit df646dfd56332a5313feac75d6d168e4c78cf404
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:58 2011 +0100

    exit round-robin vcpu loop if cpu->stopped is true
    
    Sometimes vcpus are stopped directly without going through ->stop = 1.
    Exit the VCPU execution loop in this case as well.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index c5743c4..785a104 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1098,7 +1098,7 @@ bool cpu_exec_all(void)
                 cpu_handle_debug_exception(env);
                 break;
             }
-        } else if (env->stop) {
+        } else if (env->stop || env->stopped) {
             break;
         }
     }
commit 94ad5b00a31113ed36b9d03a8db16de5535e90c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:57 2011 +0100

    always qemu_cpu_kick after unhalting a cpu
    
    This ensures env->halt_cond is broadcast, and the loop in
    qemu_tcg_wait_io_event and qemu_kvm_wait_io_event is exited
    naturally rather than through a timeout.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc.c b/hw/ppc.c
index 968aec1..de02d33 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -208,6 +208,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
                 env->halted = 0;
+                qemu_cpu_kick(env);
             }
             break;
         case PPC970_INPUT_HRESET:
@@ -300,6 +301,7 @@ static void ppc40x_set_irq (void *opaque, int pin, int level)
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
                 env->halted = 0;
+                qemu_cpu_kick(env);
             }
             break;
         case PPC40x_INPUT_DEBUG:
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 30e8a21..df3aa32 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -253,15 +253,21 @@ void cpu_check_irqs(CPUState *env)
     }
 }
 
+static void cpu_kick_irq(CPUState *env)
+{
+    env->halted = 0;
+    cpu_check_irqs(env);
+    qemu_cpu_kick(env);
+}
+
 static void cpu_set_irq(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
 
     if (level) {
         trace_sun4m_cpu_set_irq_raise(irq);
-        env->halted = 0;
         env->pil_in |= 1 << irq;
-        cpu_check_irqs(env);
+        cpu_kick_irq(env);
     } else {
         trace_sun4m_cpu_set_irq_lower(irq);
         env->pil_in &= ~(1 << irq);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 90b1ce2..d282324 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -298,6 +298,7 @@ static void cpu_kick_irq(CPUState *env)
 {
     env->halted = 0;
     cpu_check_irqs(env);
+    qemu_cpu_kick(env);
 }
 
 static void cpu_set_irq(void *opaque, int irq, int level)
@@ -306,9 +307,8 @@ static void cpu_set_irq(void *opaque, int irq, int level)
 
     if (level) {
         CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
-        env->halted = 0;
         env->pil_in |= 1 << irq;
-        cpu_check_irqs(env);
+        cpu_kick_irq(env);
     } else {
         CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
         env->pil_in &= ~(1 << irq);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b349812..6e94274 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -194,6 +194,7 @@ static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
 
     env->halted = 0;
     env->exception_index = -1;
+    qemu_cpu_kick(env);
 
     kvmint.type = type;
     kvmint.parm = parm;
commit eda48c344f35e5bd511dea3e8be56fb08c19b399
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:56 2011 +0100

    inline cpu_halted into sole caller
    
    All implementations are now the same, and there is only one caller,
    so inline the function there.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 70c3e5a..34eaedc 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -208,8 +208,13 @@ int cpu_exec(CPUState *env1)
     uint8_t *tc_ptr;
     unsigned long next_tb;
 
-    if (cpu_halted(env1) == EXCP_HALTED)
-        return EXCP_HALTED;
+    if (env1->halted) {
+        if (!cpu_has_work(env1)) {
+            return EXCP_HALTED;
+        }
+
+        env1->halted = 0;
+    }
 
     cpu_single_env = env1;
 
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index a8a38d2..6ae96d1 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -42,17 +42,6 @@ static inline int cpu_has_work(CPUState *env)
     return (env->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted)
-        return 0;
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
diff --git a/target-arm/exec.h b/target-arm/exec.h
index e4c35a3..44e1b55 100644
--- a/target-arm/exec.h
+++ b/target-arm/exec.h
@@ -32,19 +32,6 @@ static inline int cpu_has_work(CPUState *env)
             (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB));
 }
 
-static inline int cpu_halted(CPUState *env) {
-    if (!env->halted)
-        return 0;
-    /* An interrupt wakes the CPU even if the I and F CPSR bits are
-       set.  We use EXITTB to silently wake CPU without causing an
-       actual interrupt.  */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 #if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
 #endif
diff --git a/target-cris/exec.h b/target-cris/exec.h
index 34c0132..2d5d297 100644
--- a/target-cris/exec.h
+++ b/target-cris/exec.h
@@ -33,17 +33,6 @@ static inline int cpu_has_work(CPUState *env)
     return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
 }
 
-static inline int cpu_halted(CPUState *env) {
-	if (!env->halted)
-		return 0;
-
-	if (cpu_has_work(env)) {
-		env->halted = 0;
-		return 0;
-	}
-	return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
diff --git a/target-i386/exec.h b/target-i386/exec.h
index fc8945b..3e7386e 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -304,18 +304,6 @@ static inline int cpu_has_work(CPUState *env)
     return work;
 }
 
-static inline int cpu_halted(CPUState *env) {
-    /* handle exit of HALTED state */
-    if (!env->halted)
-        return 0;
-    /* disable halt condition */
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 /* load efer and update the corresponding hflags. XXX: do consistency
    checks with cpuid bits ? */
 static inline void cpu_load_efer(CPUState *env, uint64_t val)
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
index f31e06e..91daa6b 100644
--- a/target-m68k/exec.h
+++ b/target-m68k/exec.h
@@ -33,16 +33,6 @@ static inline int cpu_has_work(CPUState *env)
     return (env->interrupt_request & (CPU_INTERRUPT_HARD));
 }
 
-static inline int cpu_halted(CPUState *env) {
-    if (!env->halted)
-        return 0;
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
index ab19828..1efff30 100644
--- a/target-microblaze/exec.h
+++ b/target-microblaze/exec.h
@@ -32,17 +32,6 @@ static inline int cpu_has_work(CPUState *env)
     return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
 }
 
-static inline int cpu_halted(CPUState *env) {
-	if (!env->halted)
-		return 0;
-
-	if (cpu_has_work(env)) {
-		env->halted = 0;
-		return 0;
-	}
-	return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->sregs[SR_PC] = tb->pc;
diff --git a/target-mips/exec.h b/target-mips/exec.h
index 1273654..b3c5a13 100644
--- a/target-mips/exec.h
+++ b/target-mips/exec.h
@@ -36,17 +36,6 @@ static inline int cpu_has_work(CPUState *env)
     return has_work;
 }
 
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted)
-        return 0;
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void compute_hflags(CPUState *env)
 {
     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
index 4688ef5..f87847a 100644
--- a/target-ppc/exec.h
+++ b/target-ppc/exec.h
@@ -38,17 +38,6 @@ static inline int cpu_has_work(CPUState *env)
 }
 
 
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted)
-        return 0;
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->nip = tb->pc;
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
index bf3f264..f7893f3 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -34,18 +34,6 @@ static inline int cpu_has_work(CPUState *env)
     return env->interrupt_request & CPU_INTERRUPT_HARD; // guess
 }
 
-static inline int cpu_halted(CPUState *env)
-{
-    if (!env->halted) {
-       return 0;
-    }
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
 {
     env->psw.addr = tb->pc;
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index 61bc121..9f1c1f6 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -32,16 +32,6 @@ static inline int cpu_has_work(CPUState *env)
     return (env->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
-static inline int cpu_halted(CPUState *env) {
-    if (!env->halted)
-        return 0;
-    if (cpu_has_work(env)) {
-        env->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 #ifndef CONFIG_USER_ONLY
 #include "softmmu_exec.h"
 #endif
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index f811571..f5c221e 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -22,16 +22,6 @@ static inline int cpu_has_work(CPUState *env1)
 }
 
 
-static inline int cpu_halted(CPUState *env1) {
-    if (!env1->halted)
-        return 0;
-    if (cpu_has_work(env1)) {
-        env1->halted = 0;
-        return 0;
-    }
-    return EXCP_HALTED;
-}
-
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->pc = tb->pc;
commit 38a42e7c527f3d1fb745211b1fbb7b9af76f790f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:55 2011 +0100

    remove CONFIG_THREAD
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 5513d3e..a166de0 100755
--- a/configure
+++ b/configure
@@ -2667,7 +2667,6 @@ if test "$vnc_png" != "no" ; then
 fi
 if test "$vnc_thread" != "no" ; then
   echo "CONFIG_VNC_THREAD=y" >> $config_host_mak
-  echo "CONFIG_THREAD=y" >> $config_host_mak
 fi
 if test "$fnmatch" = "yes" ; then
   echo "CONFIG_FNMATCH=y" >> $config_host_mak
@@ -2763,7 +2762,6 @@ if test "$xen" = "yes" ; then
 fi
 if test "$io_thread" = "yes" ; then
   echo "CONFIG_IOTHREAD=y" >> $config_host_mak
-  echo "CONFIG_THREAD=y" >> $config_host_mak
 fi
 if test "$linux_aio" = "yes" ; then
   echo "CONFIG_LINUX_AIO=y" >> $config_host_mak
commit 89b48b56812a1a2d5b7edc927a7853d952e7fb38
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:54 2011 +0100

    add assertions on the owner of a QemuMutex
    
    These are already present in the Win32 implementation, add them to
    the pthread wrappers as well.  Use PTHREAD_MUTEX_ERRORCHECK for mutex
    operations. Later we'll add tracking of the owner for cond_signal/broadcast.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index e307773..8b54cc0 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -28,8 +28,12 @@ static void error_exit(int err, const char *msg)
 void qemu_mutex_init(QemuMutex *mutex)
 {
     int err;
+    pthread_mutexattr_t mutexattr;
 
-    err = pthread_mutex_init(&mutex->lock, NULL);
+    pthread_mutexattr_init(&mutexattr);
+    pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+    err = pthread_mutex_init(&mutex->lock, &mutexattr);
+    pthread_mutexattr_destroy(&mutexattr);
     if (err)
         error_exit(err, __func__);
 }
commit 96284e8973fe8d8556ef5d4aefa0807b9f22907c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:53 2011 +0100

    include qemu-thread.h early
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 09ce6fe..c5743c4 100644
--- a/cpus.c
+++ b/cpus.c
@@ -32,6 +32,7 @@
 #include "kvm.h"
 #include "exec-all.h"
 
+#include "qemu-thread.h"
 #include "cpus.h"
 #include "compatfd.h"
 
@@ -592,8 +593,6 @@ void vm_stop(int reason)
 
 #else /* CONFIG_IOTHREAD */
 
-#include "qemu-thread.h"
-
 QemuMutex qemu_global_mutex;
 static QemuMutex qemu_fair_mutex;
 
commit 9257d46d55f1fe4e8209be9a6870e339ac3266fe
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:52 2011 +0100

    add win32 qemu-thread implementation
    
    For now, qemu_cond_timedwait and qemu_mutex_timedlock are left as
    POSIX-only functions.  They can be removed later, once the patches
    that remove their uses are in.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 9e98a66..a52f42f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -142,8 +142,8 @@ endif
 common-obj-y += $(addprefix ui/, $(ui-obj-y))
 
 common-obj-y += iov.o acl.o
-common-obj-$(CONFIG_THREAD) += qemu-thread.o
-common-obj-$(CONFIG_POSIX) += compatfd.o
+common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
+common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
 common-obj-y += notify.o event_notifier.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
 
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
new file mode 100644
index 0000000..e307773
--- /dev/null
+++ b/qemu-thread-posix.c
@@ -0,0 +1,192 @@
+/*
+ * Wrappers around mutex/cond/thread functions
+ *
+ * Copyright Red Hat, Inc. 2009
+ *
+ * Author:
+ *  Marcelo Tosatti <mtosatti at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+#include "qemu-thread.h"
+
+static void error_exit(int err, const char *msg)
+{
+    fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
+    exit(1);
+}
+
+void qemu_mutex_init(QemuMutex *mutex)
+{
+    int err;
+
+    err = pthread_mutex_init(&mutex->lock, NULL);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_mutex_destroy(QemuMutex *mutex)
+{
+    int err;
+
+    err = pthread_mutex_destroy(&mutex->lock);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_mutex_lock(QemuMutex *mutex)
+{
+    int err;
+
+    err = pthread_mutex_lock(&mutex->lock);
+    if (err)
+        error_exit(err, __func__);
+}
+
+int qemu_mutex_trylock(QemuMutex *mutex)
+{
+    return pthread_mutex_trylock(&mutex->lock);
+}
+
+static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
+{
+    ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
+    ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
+    if (ts->tv_nsec >= 1000000000) {
+        ts->tv_nsec -= 1000000000;
+        ts->tv_sec++;
+    }
+}
+
+int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
+{
+    int err;
+    struct timespec ts;
+
+    clock_gettime(CLOCK_REALTIME, &ts);
+    timespec_add_ms(&ts, msecs);
+
+    err = pthread_mutex_timedlock(&mutex->lock, &ts);
+    if (err && err != ETIMEDOUT)
+        error_exit(err, __func__);
+    return err;
+}
+
+void qemu_mutex_unlock(QemuMutex *mutex)
+{
+    int err;
+
+    err = pthread_mutex_unlock(&mutex->lock);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_cond_init(QemuCond *cond)
+{
+    int err;
+
+    err = pthread_cond_init(&cond->cond, NULL);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_cond_destroy(QemuCond *cond)
+{
+    int err;
+
+    err = pthread_cond_destroy(&cond->cond);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_cond_signal(QemuCond *cond)
+{
+    int err;
+
+    err = pthread_cond_signal(&cond->cond);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_cond_broadcast(QemuCond *cond)
+{
+    int err;
+
+    err = pthread_cond_broadcast(&cond->cond);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
+{
+    int err;
+
+    err = pthread_cond_wait(&cond->cond, &mutex->lock);
+    if (err)
+        error_exit(err, __func__);
+}
+
+int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
+{
+    struct timespec ts;
+    int err;
+
+    clock_gettime(CLOCK_REALTIME, &ts);
+    timespec_add_ms(&ts, msecs);
+
+    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
+    if (err && err != ETIMEDOUT)
+        error_exit(err, __func__);
+    return err;
+}
+
+void qemu_thread_create(QemuThread *thread,
+                       void *(*start_routine)(void*),
+                       void *arg)
+{
+    int err;
+
+    /* Leave signal handling to the iothread.  */
+    sigset_t set, oldset;
+
+    sigfillset(&set);
+    pthread_sigmask(SIG_SETMASK, &set, &oldset);
+    err = pthread_create(&thread->thread, NULL, start_routine, arg);
+    if (err)
+        error_exit(err, __func__);
+
+    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+}
+
+void qemu_thread_signal(QemuThread *thread, int sig)
+{
+    int err;
+
+    err = pthread_kill(thread->thread, sig);
+    if (err)
+        error_exit(err, __func__);
+}
+
+void qemu_thread_get_self(QemuThread *thread)
+{
+    thread->thread = pthread_self();
+}
+
+int qemu_thread_is_self(QemuThread *thread)
+{
+   return pthread_equal(pthread_self(), thread->thread);
+}
+
+void qemu_thread_exit(void *retval)
+{
+    pthread_exit(retval);
+}
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
new file mode 100644
index 0000000..7af371c
--- /dev/null
+++ b/qemu-thread-posix.h
@@ -0,0 +1,18 @@
+#ifndef __QEMU_THREAD_POSIX_H
+#define __QEMU_THREAD_POSIX_H 1
+#include "pthread.h"
+
+struct QemuMutex {
+    pthread_mutex_t lock;
+};
+
+struct QemuCond {
+    pthread_cond_t cond;
+};
+
+struct QemuThread {
+    pthread_t thread;
+};
+
+void qemu_thread_signal(QemuThread *thread, int sig);
+#endif
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
new file mode 100644
index 0000000..2edcb1a
--- /dev/null
+++ b/qemu-thread-win32.c
@@ -0,0 +1,260 @@
+/*
+ * Win32 implementation for mutex/cond/thread functions
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Author:
+ *  Paolo Bonzini <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include "qemu-common.h"
+#include "qemu-thread.h"
+#include <process.h>
+#include <assert.h>
+#include <limits.h>
+
+static void error_exit(int err, const char *msg)
+{
+    char *pstr;
+
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                  NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
+    fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
+    LocalFree(pstr);
+    exit(1);
+}
+
+void qemu_mutex_init(QemuMutex *mutex)
+{
+    mutex->owner = 0;
+    InitializeCriticalSection(&mutex->lock);
+}
+
+void qemu_mutex_lock(QemuMutex *mutex)
+{
+    EnterCriticalSection(&mutex->lock);
+
+    /* Win32 CRITICAL_SECTIONs are recursive.  Assert that we're not
+     * using them as such.
+     */
+    assert(mutex->owner == 0);
+    mutex->owner = GetCurrentThreadId();
+}
+
+int qemu_mutex_trylock(QemuMutex *mutex)
+{
+    int owned;
+
+    owned = TryEnterCriticalSection(&mutex->lock);
+    if (owned) {
+        assert(mutex->owner == 0);
+        mutex->owner = GetCurrentThreadId();
+    }
+    return !owned;
+}
+
+void qemu_mutex_unlock(QemuMutex *mutex)
+{
+    assert(mutex->owner == GetCurrentThreadId());
+    mutex->owner = 0;
+    LeaveCriticalSection(&mutex->lock);
+}
+
+void qemu_cond_init(QemuCond *cond)
+{
+    memset(cond, 0, sizeof(*cond));
+
+    cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+    if (!cond->sema) {
+        error_exit(GetLastError(), __func__);
+    }
+    cond->continue_event = CreateEvent(NULL,    /* security */
+                                       FALSE,   /* auto-reset */
+                                       FALSE,   /* not signaled */
+                                       NULL);   /* name */
+    if (!cond->continue_event) {
+        error_exit(GetLastError(), __func__);
+    }
+}
+
+void qemu_cond_signal(QemuCond *cond)
+{
+    DWORD result;
+
+    /*
+     * Signal only when there are waiters.  cond->waiters is
+     * incremented by pthread_cond_wait under the external lock,
+     * so we are safe about that.
+     */
+    if (cond->waiters == 0) {
+        return;
+    }
+
+    /*
+     * Waiting threads decrement it outside the external lock, but
+     * only if another thread is executing pthread_cond_broadcast and
+     * has the mutex.  So, it also cannot be decremented concurrently
+     * with this particular access.
+     */
+    cond->target = cond->waiters - 1;
+    result = SignalObjectAndWait(cond->sema, cond->continue_event,
+                                 INFINITE, FALSE);
+    if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
+        error_exit(GetLastError(), __func__);
+    }
+}
+
+void qemu_cond_broadcast(QemuCond *cond)
+{
+    BOOLEAN result;
+    /*
+     * As in pthread_cond_signal, access to cond->waiters and
+     * cond->target is locked via the external mutex.
+     */
+    if (cond->waiters == 0) {
+        return;
+    }
+
+    cond->target = 0;
+    result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
+    if (!result) {
+        error_exit(GetLastError(), __func__);
+    }
+
+    /*
+     * At this point all waiters continue. Each one takes its
+     * slice of the semaphore. Now it's our turn to wait: Since
+     * the external mutex is held, no thread can leave cond_wait,
+     * yet. For this reason, we can be sure that no thread gets
+     * a chance to eat *more* than one slice. OTOH, it means
+     * that the last waiter must send us a wake-up.
+     */
+    WaitForSingleObject(cond->continue_event, INFINITE);
+}
+
+void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
+{
+    /*
+     * This access is protected under the mutex.
+     */
+    cond->waiters++;
+
+    /*
+     * Unlock external mutex and wait for signal.
+     * NOTE: we've held mutex locked long enough to increment
+     * waiters count above, so there's no problem with
+     * leaving mutex unlocked before we wait on semaphore.
+     */
+    qemu_mutex_unlock(mutex);
+    WaitForSingleObject(cond->sema, INFINITE);
+
+    /* Now waiters must rendez-vous with the signaling thread and
+     * let it continue.  For cond_broadcast this has heavy contention
+     * and triggers thundering herd.  So goes life.
+     *
+     * Decrease waiters count.  The mutex is not taken, so we have
+     * to do this atomically.
+     *
+     * All waiters contend for the mutex at the end of this function
+     * until the signaling thread relinquishes it.  To ensure
+     * each waiter consumes exactly one slice of the semaphore,
+     * the signaling thread stops until it is told by the last
+     * waiter that it can go on.
+     */
+    if (InterlockedDecrement(&cond->waiters) == cond->target) {
+        SetEvent(cond->continue_event);
+    }
+
+    qemu_mutex_lock(mutex);
+}
+
+struct QemuThreadData {
+    QemuThread *thread;
+    void *(*start_routine)(void *);
+    void *arg;
+};
+
+static int qemu_thread_tls_index = TLS_OUT_OF_INDEXES;
+
+static unsigned __stdcall win32_start_routine(void *arg)
+{
+    struct QemuThreadData data = *(struct QemuThreadData *) arg;
+    QemuThread *thread = data.thread;
+
+    free(arg);
+    TlsSetValue(qemu_thread_tls_index, thread);
+
+    /*
+     * Use DuplicateHandle instead of assigning thread->thread in the
+     * creating thread to avoid races.  It's simpler this way than with
+     * synchronization.
+     */
+    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+                    GetCurrentProcess(), &thread->thread,
+                    0, FALSE, DUPLICATE_SAME_ACCESS);
+
+    qemu_thread_exit(data.start_routine(data.arg));
+    abort();
+}
+
+void qemu_thread_exit(void *arg)
+{
+    QemuThread *thread = TlsGetValue(qemu_thread_tls_index);
+    thread->ret = arg;
+    CloseHandle(thread->thread);
+    thread->thread = NULL;
+    ExitThread(0);
+}
+
+static inline void qemu_thread_init(void)
+{
+    if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) {
+        qemu_thread_tls_index = TlsAlloc();
+        if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) {
+            error_exit(ERROR_NO_SYSTEM_RESOURCES, __func__);
+        }
+    }
+}
+
+
+void qemu_thread_create(QemuThread *thread,
+                       void *(*start_routine)(void *),
+                       void *arg)
+{
+    HANDLE hThread;
+
+    struct QemuThreadData *data;
+    qemu_thread_init();
+    data = qemu_malloc(sizeof *data);
+    data->thread = thread;
+    data->start_routine = start_routine;
+    data->arg = arg;
+
+    hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
+                                      data, 0, NULL);
+    if (!hThread) {
+        error_exit(GetLastError(), __func__);
+    }
+    CloseHandle(hThread);
+}
+
+void qemu_thread_get_self(QemuThread *thread)
+{
+    if (!thread->thread) {
+        /* In the main thread of the process.  Initialize the QemuThread
+           pointer in TLS, and use the dummy GetCurrentThread handle as
+           the identifier for qemu_thread_is_self.  */
+        qemu_thread_init();
+        TlsSetValue(qemu_thread_tls_index, thread);
+        thread->thread = GetCurrentThread();
+    }
+}
+
+int qemu_thread_is_self(QemuThread *thread)
+{
+    QemuThread *this_thread = TlsGetValue(qemu_thread_tls_index);
+    return this_thread->thread == thread->thread;
+}
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
new file mode 100644
index 0000000..878f86a
--- /dev/null
+++ b/qemu-thread-win32.h
@@ -0,0 +1,21 @@
+#ifndef __QEMU_THREAD_WIN32_H
+#define __QEMU_THREAD_WIN32_H 1
+#include "windows.h"
+
+struct QemuMutex {
+    CRITICAL_SECTION lock;
+    LONG owner;
+};
+
+struct QemuCond {
+    LONG waiters, target;
+    HANDLE sema;
+    HANDLE continue_event;
+};
+
+struct QemuThread {
+    HANDLE thread;
+    void *ret;
+};
+
+#endif
diff --git a/qemu-thread.c b/qemu-thread.c
deleted file mode 100644
index e307773..0000000
--- a/qemu-thread.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Wrappers around mutex/cond/thread functions
- *
- * Copyright Red Hat, Inc. 2009
- *
- * Author:
- *  Marcelo Tosatti <mtosatti at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include "qemu-thread.h"
-
-static void error_exit(int err, const char *msg)
-{
-    fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
-    exit(1);
-}
-
-void qemu_mutex_init(QemuMutex *mutex)
-{
-    int err;
-
-    err = pthread_mutex_init(&mutex->lock, NULL);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_mutex_destroy(QemuMutex *mutex)
-{
-    int err;
-
-    err = pthread_mutex_destroy(&mutex->lock);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_mutex_lock(QemuMutex *mutex)
-{
-    int err;
-
-    err = pthread_mutex_lock(&mutex->lock);
-    if (err)
-        error_exit(err, __func__);
-}
-
-int qemu_mutex_trylock(QemuMutex *mutex)
-{
-    return pthread_mutex_trylock(&mutex->lock);
-}
-
-static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
-{
-    ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
-    ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
-    if (ts->tv_nsec >= 1000000000) {
-        ts->tv_nsec -= 1000000000;
-        ts->tv_sec++;
-    }
-}
-
-int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
-{
-    int err;
-    struct timespec ts;
-
-    clock_gettime(CLOCK_REALTIME, &ts);
-    timespec_add_ms(&ts, msecs);
-
-    err = pthread_mutex_timedlock(&mutex->lock, &ts);
-    if (err && err != ETIMEDOUT)
-        error_exit(err, __func__);
-    return err;
-}
-
-void qemu_mutex_unlock(QemuMutex *mutex)
-{
-    int err;
-
-    err = pthread_mutex_unlock(&mutex->lock);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_cond_init(QemuCond *cond)
-{
-    int err;
-
-    err = pthread_cond_init(&cond->cond, NULL);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_cond_destroy(QemuCond *cond)
-{
-    int err;
-
-    err = pthread_cond_destroy(&cond->cond);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_cond_signal(QemuCond *cond)
-{
-    int err;
-
-    err = pthread_cond_signal(&cond->cond);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_cond_broadcast(QemuCond *cond)
-{
-    int err;
-
-    err = pthread_cond_broadcast(&cond->cond);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
-{
-    int err;
-
-    err = pthread_cond_wait(&cond->cond, &mutex->lock);
-    if (err)
-        error_exit(err, __func__);
-}
-
-int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
-{
-    struct timespec ts;
-    int err;
-
-    clock_gettime(CLOCK_REALTIME, &ts);
-    timespec_add_ms(&ts, msecs);
-
-    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
-    if (err && err != ETIMEDOUT)
-        error_exit(err, __func__);
-    return err;
-}
-
-void qemu_thread_create(QemuThread *thread,
-                       void *(*start_routine)(void*),
-                       void *arg)
-{
-    int err;
-
-    /* Leave signal handling to the iothread.  */
-    sigset_t set, oldset;
-
-    sigfillset(&set);
-    pthread_sigmask(SIG_SETMASK, &set, &oldset);
-    err = pthread_create(&thread->thread, NULL, start_routine, arg);
-    if (err)
-        error_exit(err, __func__);
-
-    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-}
-
-void qemu_thread_signal(QemuThread *thread, int sig)
-{
-    int err;
-
-    err = pthread_kill(thread->thread, sig);
-    if (err)
-        error_exit(err, __func__);
-}
-
-void qemu_thread_get_self(QemuThread *thread)
-{
-    thread->thread = pthread_self();
-}
-
-int qemu_thread_is_self(QemuThread *thread)
-{
-   return pthread_equal(pthread_self(), thread->thread);
-}
-
-void qemu_thread_exit(void *retval)
-{
-    pthread_exit(retval);
-}
diff --git a/qemu-thread.h b/qemu-thread.h
index add97bf..acdb6b2 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -1,24 +1,16 @@
 #ifndef __QEMU_THREAD_H
 #define __QEMU_THREAD_H 1
-#include "semaphore.h"
-#include "pthread.h"
-
-struct QemuMutex {
-    pthread_mutex_t lock;
-};
-
-struct QemuCond {
-    pthread_cond_t cond;
-};
-
-struct QemuThread {
-    pthread_t thread;
-};
 
 typedef struct QemuMutex QemuMutex;
 typedef struct QemuCond QemuCond;
 typedef struct QemuThread QemuThread;
 
+#ifdef _WIN32
+#include "qemu-thread-win32.h"
+#else
+#include "qemu-thread-posix.h"
+#endif
+
 void qemu_mutex_init(QemuMutex *mutex);
 void qemu_mutex_destroy(QemuMutex *mutex);
 void qemu_mutex_lock(QemuMutex *mutex);
@@ -28,6 +20,12 @@ void qemu_mutex_unlock(QemuMutex *mutex);
 
 void qemu_cond_init(QemuCond *cond);
 void qemu_cond_destroy(QemuCond *cond);
+
+/*
+ * IMPORTANT: The implementation does not guarantee that pthread_cond_signal
+ * and pthread_cond_broadcast can be called except while the same mutex is
+ * held as in the corresponding pthread_cond_wait calls!
+ */
 void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
@@ -36,7 +34,6 @@ int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs);
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
                        void *arg);
-void qemu_thread_signal(QemuThread *thread, int sig);
 void qemu_thread_get_self(QemuThread *thread);
 int qemu_thread_is_self(QemuThread *thread);
 void qemu_thread_exit(void *retval);
commit b7680cb6078bd7294a3dd86473d3f2fdee991dd0
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Mar 12 17:43:51 2011 +0100

    Refactor thread retrieval and check
    
    We have qemu_cpu_self and qemu_thread_self. The latter is retrieving the
    current thread, the former is checking for equality (using CPUState). We
    also have qemu_thread_equal which is only used like qemu_cpu_self.
    
    This refactors the interfaces, creating qemu_cpu_is_self and
    qemu_thread_is_self as well ass qemu_thread_get_self.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 0f33945..09ce6fe 100644
--- a/cpus.c
+++ b/cpus.c
@@ -531,7 +531,7 @@ void qemu_init_vcpu(void *_env)
     }
 }
 
-int qemu_cpu_self(void *env)
+int qemu_cpu_is_self(void *env)
 {
     return 1;
 }
@@ -699,7 +699,7 @@ int qemu_init_main_loop(void)
     qemu_mutex_init(&qemu_global_mutex);
     qemu_mutex_lock(&qemu_global_mutex);
 
-    qemu_thread_self(&io_thread);
+    qemu_thread_get_self(&io_thread);
 
     return 0;
 }
@@ -714,7 +714,7 @@ void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 {
     struct qemu_work_item wi;
 
-    if (qemu_cpu_self(env)) {
+    if (qemu_cpu_is_self(env)) {
         func(data);
         return;
     }
@@ -808,7 +808,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     int r;
 
     qemu_mutex_lock(&qemu_global_mutex);
-    qemu_thread_self(env->thread);
+    qemu_thread_get_self(env->thread);
 
     r = kvm_init_vcpu(env);
     if (r < 0) {
@@ -845,7 +845,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     CPUState *env = arg;
 
     qemu_tcg_init_cpu_signals();
-    qemu_thread_self(env->thread);
+    qemu_thread_get_self(env->thread);
 
     /* signal CPU creation */
     qemu_mutex_lock(&qemu_global_mutex);
@@ -888,14 +888,11 @@ void qemu_cpu_kick_self(void)
     }
 }
 
-int qemu_cpu_self(void *_env)
+int qemu_cpu_is_self(void *_env)
 {
     CPUState *env = _env;
-    QemuThread this;
 
-    qemu_thread_self(&this);
-
-    return qemu_thread_equal(&this, env->thread);
+    return qemu_thread_is_self(env->thread);
 }
 
 void qemu_mutex_lock_iothread(void)
@@ -1023,10 +1020,7 @@ void cpu_stop_current(void)
 
 void vm_stop(int reason)
 {
-    QemuThread me;
-    qemu_thread_self(&me);
-
-    if (!qemu_thread_equal(&me, &io_thread)) {
+    if (!qemu_thread_is_self(&io_thread)) {
         qemu_system_vmstop_request(reason);
         /*
          * FIXME: should not return to device code in case
diff --git a/exec.c b/exec.c
index 81f08b7..3d78063 100644
--- a/exec.c
+++ b/exec.c
@@ -1640,7 +1640,7 @@ void cpu_interrupt(CPUState *env, int mask)
      * If called from iothread context, wake the target cpu in
      * case its halted.
      */
-    if (!qemu_cpu_self(env)) {
+    if (!qemu_cpu_is_self(env)) {
         qemu_cpu_kick(env);
         return;
     }
diff --git a/qemu-common.h b/qemu-common.h
index 18e648f..3fe1719 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -290,7 +290,7 @@ void qemu_notify_event(void);
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
 void qemu_cpu_kick_self(void);
-int qemu_cpu_self(void *env);
+int qemu_cpu_is_self(void *env);
 
 /* work queue */
 struct qemu_work_item {
diff --git a/qemu-thread.c b/qemu-thread.c
index fbc78fe..e307773 100644
--- a/qemu-thread.c
+++ b/qemu-thread.c
@@ -176,14 +176,14 @@ void qemu_thread_signal(QemuThread *thread, int sig)
         error_exit(err, __func__);
 }
 
-void qemu_thread_self(QemuThread *thread)
+void qemu_thread_get_self(QemuThread *thread)
 {
     thread->thread = pthread_self();
 }
 
-int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
+int qemu_thread_is_self(QemuThread *thread)
 {
-   return pthread_equal(thread1->thread, thread2->thread);
+   return pthread_equal(pthread_self(), thread->thread);
 }
 
 void qemu_thread_exit(void *retval)
diff --git a/qemu-thread.h b/qemu-thread.h
index 19bb30c..add97bf 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -37,8 +37,8 @@ void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
                        void *arg);
 void qemu_thread_signal(QemuThread *thread, int sig);
-void qemu_thread_self(QemuThread *thread);
-int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2);
+void qemu_thread_get_self(QemuThread *thread);
+int qemu_thread_is_self(QemuThread *thread);
 void qemu_thread_exit(void *retval);
 
 #endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0aa0a41..1f12cbf 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1355,7 +1355,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
 {
     int ret;
 
-    assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+    assert(cpu_is_stopped(env) || qemu_cpu_is_self(env));
 
     ret = kvm_getput_regs(env, 1);
     if (ret < 0) {
@@ -1403,7 +1403,7 @@ int kvm_arch_get_registers(CPUState *env)
 {
     int ret;
 
-    assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+    assert(cpu_is_stopped(env) || qemu_cpu_is_self(env));
 
     ret = kvm_getput_regs(env, 0);
     if (ret < 0) {
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index f596247..1dfa6c3 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -303,7 +303,7 @@ static void *vnc_worker_thread(void *arg)
 {
     VncJobQueue *queue = arg;
 
-    qemu_thread_self(&queue->thread);
+    qemu_thread_get_self(&queue->thread);
 
     while (!vnc_worker_thread_loop(queue)) ;
     vnc_queue_clear(queue);
commit 68c23e5520e8286d79d96ab47c0ea722ceb75041
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:50 2011 +0100

    use win32 timer queues
    
    Multimedia timers are only useful for compatibility with Windows NT 4.0
    and earlier.  Plus, the implementation in Wine is extremely heavyweight.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 122e7ed..1939d6b 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -200,11 +200,6 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 
 #ifdef _WIN32
 
-struct qemu_alarm_win32 {
-    MMRESULT timerId;
-    unsigned int period;
-} alarm_win32_data = {0, 0};
-
 static int win32_start_timer(struct qemu_alarm_timer *t);
 static void win32_stop_timer(struct qemu_alarm_timer *t);
 static void win32_rearm_timer(struct qemu_alarm_timer *t);
@@ -298,9 +293,9 @@ static struct qemu_alarm_timer alarm_timers[] = {
     {"unix", unix_start_timer, unix_stop_timer, NULL, NULL},
 #else
     {"dynticks", win32_start_timer,
-     win32_stop_timer, win32_rearm_timer, &alarm_win32_data},
+     win32_stop_timer, win32_rearm_timer, NULL},
     {"win32", win32_start_timer,
-     win32_stop_timer, NULL, &alarm_win32_data},
+     win32_stop_timer, NULL, NULL},
 #endif
     {NULL, }
 };
@@ -636,9 +631,7 @@ void qemu_run_all_timers(void)
 static int64_t qemu_next_alarm_deadline(void);
 
 #ifdef _WIN32
-static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
-                                        DWORD_PTR dwUser, DWORD_PTR dw1,
-                                        DWORD_PTR dw2)
+static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
 #else
 static void host_alarm_handler(int host_signum)
 #endif
@@ -961,50 +954,45 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
 
 static int win32_start_timer(struct qemu_alarm_timer *t)
 {
-    TIMECAPS tc;
-    struct qemu_alarm_win32 *data = t->priv;
-    UINT flags;
-
-    memset(&tc, 0, sizeof(tc));
-    timeGetDevCaps(&tc, sizeof(tc));
-
-    data->period = tc.wPeriodMin;
-    timeBeginPeriod(data->period);
-
-    flags = TIME_CALLBACK_FUNCTION;
-    if (alarm_has_dynticks(t))
-        flags |= TIME_ONESHOT;
-    else
-        flags |= TIME_PERIODIC;
-
-    data->timerId = timeSetEvent(1,         // interval (ms)
-                        data->period,       // resolution
-                        host_alarm_handler, // function
-                        (DWORD)t,           // parameter
-                        flags);
-
-    if (!data->timerId) {
+    HANDLE hTimer;
+    BOOLEAN success;
+
+    /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
+       is zero) that has already expired, the timer is not updated.  Since
+       creating a new timer is relatively expensive, set a bogus one-hour
+       interval in the dynticks case.  */
+    success = CreateTimerQueueTimer(&hTimer,
+                          NULL,
+                          host_alarm_handler,
+                          t,
+                          1,
+                          alarm_has_dynticks(t) ? 3600000 : 1,
+                          WT_EXECUTEINTIMERTHREAD);
+
+    if (!success) {
         fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
                 GetLastError());
-        timeEndPeriod(data->period);
         return -1;
     }
 
+    t->priv = (PVOID) hTimer;
     return 0;
 }
 
 static void win32_stop_timer(struct qemu_alarm_timer *t)
 {
-    struct qemu_alarm_win32 *data = t->priv;
+    HANDLE hTimer = t->priv;
 
-    timeKillEvent(data->timerId);
-    timeEndPeriod(data->period);
+    if (hTimer) {
+        DeleteTimerQueueTimer(NULL, hTimer, NULL);
+    }
 }
 
 static void win32_rearm_timer(struct qemu_alarm_timer *t)
 {
-    struct qemu_alarm_win32 *data = t->priv;
+    HANDLE hTimer = t->priv;
     int nearest_delta_ms;
+    BOOLEAN success;
 
     assert(alarm_has_dynticks(t));
     if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -1012,25 +1000,21 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
         !active_timers[QEMU_CLOCK_HOST])
         return;
 
-    timeKillEvent(data->timerId);
-
     nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
     if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;
     }
-    data->timerId = timeSetEvent(nearest_delta_ms,
-                        data->period,
-                        host_alarm_handler,
-                        (DWORD)t,
-                        TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
-
-    if (!data->timerId) {
-        fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
-                GetLastError());
+    success = ChangeTimerQueueTimer(NULL,
+                                    hTimer,
+                                    nearest_delta_ms,
+                                    3600000);
 
-        timeEndPeriod(data->period);
-        exit(1);
+    if (!success) {
+        fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
+                GetLastError());
+        exit(-1);
     }
+
 }
 
 #endif /* _WIN32 */
commit cfced5b2e620d7cc44844a550db5488ee348dffc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:49 2011 +0100

    implement win32 dynticks timer
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 88c7b28..122e7ed 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -1004,6 +1004,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
 static void win32_rearm_timer(struct qemu_alarm_timer *t)
 {
     struct qemu_alarm_win32 *data = t->priv;
+    int nearest_delta_ms;
 
     assert(alarm_has_dynticks(t));
     if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -1013,7 +1014,11 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
 
     timeKillEvent(data->timerId);
 
-    data->timerId = timeSetEvent(1,
+    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+    if (nearest_delta_ms < 1) {
+        nearest_delta_ms = 1;
+    }
+    data->timerId = timeSetEvent(nearest_delta_ms,
                         data->period,
                         host_alarm_handler,
                         (DWORD)t,
commit 9931b2f4c722655d33f886181374498a39c3f489
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Mar 12 17:43:48 2011 +0100

    unlock iothread during WaitForMultipleObjects
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-win32.c b/os-win32.c
index b214e6a..c971d92 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -140,7 +140,9 @@ void os_host_main_loop_wait(int *timeout)
         int err;
         WaitObjects *w = &wait_objects;
 
+        qemu_mutex_unlock_iothread();
         ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+        qemu_mutex_lock_iothread();
         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
             if (w->func[ret - WAIT_OBJECT_0])
                 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
commit 913895ab96507db2bc448d3ae72a409407172d2e
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Mar 12 17:43:56 2011 +0100

    hw/fmopl: Fix buffer access out-of-bounds errors
    
    Index 75 is one too large for AR_TABLE[75], DR_TABLE[75].
    This error was reported by cppcheck.
    
    hw/fmopl.c:600: error: Buffer access out-of-bounds: OPL.AR_TABLE
    hw/fmopl.c:601: error: Buffer access out-of-bounds: OPL.DR_TABLE
    
    Fix this by limiting the access to the allowed range.
    MultiArcadeMachineEmulator has newer versions of fmopl,
    but using these requires more efforts.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Reviewed-by: malc <av1474 at comtv.ru>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/fmopl.c b/hw/fmopl.c
index 3df1806..d8a0f36 100644
--- a/hw/fmopl.c
+++ b/hw/fmopl.c
@@ -45,6 +45,10 @@
 #define PI 3.14159265358979323846
 #endif
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
 /* -------------------- for debug --------------------- */
 /* #define OPL_OUTPUT_LOG */
 #ifdef OPL_OUTPUT_LOG
@@ -595,7 +599,7 @@ static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
 		OPL->AR_TABLE[i] = rate / ARRATE;
 		OPL->DR_TABLE[i] = rate / DRRATE;
 	}
-	for (i = 60;i < 76;i++)
+	for (i = 60; i < ARRAY_SIZE(OPL->AR_TABLE); i++)
 	{
 		OPL->AR_TABLE[i] = EG_AED-1;
 		OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
commit 7165448a913bd8f757f588e8f1581c170d8b1775
Author: William Dauchy <wdauchy at gmail.com>
Date:   Sun Mar 6 22:27:18 2011 +0100

    moving eeprom initialization
    
    The initialization should not be only on reset but also when initializing
    the device.
    It resolves a bug when hot plugging a pci network device: the mac address
    was always null.
    
    Signed-off-by: William Dauchy <wdauchy at gmail.com>
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pcnet.c b/hw/pcnet.c
index 6dfdcc4..d3d5661 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1557,35 +1557,6 @@ uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
 void pcnet_h_reset(void *opaque)
 {
     PCNetState *s = opaque;
-    int i;
-    uint16_t checksum;
-
-    /* Initialize the PROM */
-
-    /*
-      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
-      page 95
-    */
-    memcpy(s->prom, s->conf.macaddr.a, 6);
-    /* Reserved Location: must be 00h */
-    s->prom[6] = s->prom[7] = 0x00;
-    /* Reserved Location: must be 00h */
-    s->prom[8] = 0x00;
-    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
-    s->prom[9] = 0x11;
-    /* User programmable space, init with 0 */
-    s->prom[10] = s->prom[11] = 0x00;
-    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
-       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
-    s->prom[12] = s->prom[13] = 0x00;
-    /* Must be ASCII W (57h) if compatibility to AMD
-       driver software is desired */
-    s->prom[14] = s->prom[15] = 0x57;
-
-    for (i = 0,checksum = 0; i < 16; i++)
-        checksum += s->prom[i];
-    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
-
 
     s->bcr[BCR_MSRDA] = 0x0005;
     s->bcr[BCR_MSWRA] = 0x0005;
@@ -1752,6 +1723,9 @@ void pcnet_common_cleanup(PCNetState *d)
 
 int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
 {
+    int i;
+    uint16_t checksum;
+
     s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
@@ -1760,5 +1734,32 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
 
     add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy at 0");
 
+    /* Initialize the PROM */
+
+    /*
+      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
+      page 95
+    */
+    memcpy(s->prom, s->conf.macaddr.a, 6);
+    /* Reserved Location: must be 00h */
+    s->prom[6] = s->prom[7] = 0x00;
+    /* Reserved Location: must be 00h */
+    s->prom[8] = 0x00;
+    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
+    s->prom[9] = 0x11;
+    /* User programmable space, init with 0 */
+    s->prom[10] = s->prom[11] = 0x00;
+    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
+       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
+    s->prom[12] = s->prom[13] = 0x00;
+    /* Must be ASCII W (57h) if compatibility to AMD
+       driver software is desired */
+    s->prom[14] = s->prom[15] = 0x57;
+
+    for (i = 0, checksum = 0; i < 16; i++) {
+        checksum += s->prom[i];
+    }
+    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
+
     return 0;
 }
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index a22530c..7a87522 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -1189,18 +1189,6 @@ static void rtl8139_reset(DeviceState *d)
 
     rtl8139_update_irq(s);
 
-    /* prepare eeprom */
-    s->eeprom.contents[0] = 0x8129;
-#if 1
-    // PCI vendor and device ID should be mirrored here
-    s->eeprom.contents[1] = PCI_VENDOR_ID_REALTEK;
-    s->eeprom.contents[2] = PCI_DEVICE_ID_REALTEK_8139;
-#endif
-
-    s->eeprom.contents[7] = s->conf.macaddr.a[0] | s->conf.macaddr.a[1] << 8;
-    s->eeprom.contents[8] = s->conf.macaddr.a[2] | s->conf.macaddr.a[3] << 8;
-    s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
-
     /* mark all status registers as owned by host */
     for (i = 0; i < 4; ++i)
     {
@@ -3392,6 +3380,17 @@ static int pci_rtl8139_init(PCIDevice *dev)
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
+    /* prepare eeprom */
+    s->eeprom.contents[0] = 0x8129;
+#if 1
+    /* PCI vendor and device ID should be mirrored here */
+    s->eeprom.contents[1] = PCI_VENDOR_ID_REALTEK;
+    s->eeprom.contents[2] = PCI_DEVICE_ID_REALTEK_8139;
+#endif
+    s->eeprom.contents[7] = s->conf.macaddr.a[0] | s->conf.macaddr.a[1] << 8;
+    s->eeprom.contents[8] = s->conf.macaddr.a[2] | s->conf.macaddr.a[3] << 8;
+    s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
+
     s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf,
                           dev->qdev.info->name, dev->qdev.id, s);
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
commit e14c8062f4c4c336c6e5fa5b51472ffff5f3fe38
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 12 09:52:25 2011 +0000

    pc: fix wrong CMOS values for floppy drives
    
    Before commit 63ffb564dca94f8bda01ed6d209784104630a4d2, states for
    floppy drives were calculated in fdc.c:fd_revalidate(). There it is
    also considered whether a disk is inserted or not. The commit didn't copy
    the logic completely to pc.c, which caused a regression.
    
    Fix by adding the same check also to pc.c.
    
    Reported-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Tested-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 5966bf1..4d67d9f 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -382,7 +382,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     /* floppy type */
     for (i = 0; i < 2; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
-        if (fd[i]) {
+        if (fd[i] && bdrv_is_inserted(fd[i]->bdrv)) {
             bdrv_get_floppy_geometry_hint(fd[i]->bdrv, &nb_heads, &max_track,
                                           &last_sect, FDRIVE_DRV_NONE,
                                           &fd_type[i]);
commit c4374bb7533c2c8f999526148113012dc1f436ae
Author: Michal Simek <monstr at monstr.eu>
Date:   Fri Mar 4 14:39:31 2011 +0100

    microblaze: Add PVR for writeback cache, endians
    
    Specify PVR for writeback cache, endians and others.
    
    Signed-off-by: Michal Simek <monstr at monstr.eu>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3aa28bf..14d4d42 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -110,6 +110,9 @@ struct CPUMBState;
 #define PVR0_USE_ICACHE_MASK            0x02000000
 #define PVR0_USE_DCACHE_MASK            0x01000000
 #define PVR0_USE_MMU                    0x00800000      /* new */
+#define PVR0_USE_BTC			0x00400000
+#define PVR0_ENDI			0x00200000
+#define PVR0_FAULT			0x00100000
 #define PVR0_VERSION_MASK               0x0000FF00
 #define PVR0_USER1_MASK                 0x000000FF
 
@@ -169,6 +172,7 @@ struct CPUMBState;
 #define PVR5_DCACHE_ALLOW_WR_MASK       0x01000000
 #define PVR5_DCACHE_LINE_LEN_MASK       0x00E00000
 #define PVR5_DCACHE_BYTE_SIZE_MASK      0x001F0000
+#define PVR5_DCACHE_WRITEBACK_MASK      0x00004000
 
 /* ICache base address PVR mask */
 #define PVR6_ICACHE_BASEADDR_MASK       0xFFFFFFFF
commit 73ad9e62a3d78c909505c04113aed3dac60f5b2d
Author: Michal Simek <monstr at monstr.eu>
Date:   Fri Mar 4 12:31:14 2011 +0100

    microblaze: Fix PetaLogix company name
    
    trivial fix.
    
    Signed-off-by: Michal Simek <monstr at monstr.eu>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 6ef4e65..4dcdfbd 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -217,7 +217,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
 
 static QEMUMachine petalogix_s3adsp1800_machine = {
     .name = "petalogix-s3adsp1800",
-    .desc = "Petalogix linux refdesign for xilinx Spartan 3ADSP1800",
+    .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
     .init = petalogix_s3adsp1800_init,
     .is_default = 1
 };
commit 98fa4a593220c273f989de9b5af1ad2f132e14d5
Merge: f6317a6... ddca9fb...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 11 08:03:55 2011 -0600

    Merge remote branch 'stefanha/tracing' into staging

commit f6317a6ef16841d9d4a90e3aa664f715e26f978c
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:56 2011 +0100

    vmstate: move timers to use test instead of version
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 4e09f18..1b09039 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -399,6 +399,15 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_value(_state, _field, _type),       \
 }
 
+#define VMSTATE_POINTER_TEST(_field, _state, _test, _info, _type) {  \
+    .name       = (stringify(_field)),                               \
+    .info       = &(_info),                                          \
+    .field_exists = (_test),                                         \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_SINGLE|VMS_POINTER,                            \
+    .offset     = vmstate_offset_value(_state, _field, _type),       \
+}
+
 #define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) {\
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
@@ -766,11 +775,11 @@ extern const VMStateDescription vmstate_usb_device;
 #define VMSTATE_UINT32_TEST(_f, _s, _t)                                  \
     VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t)
 
-#define VMSTATE_TIMER_V(_f, _s, _v)                                   \
-    VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *)
+#define VMSTATE_TIMER_TEST(_f, _s, _test)                             \
+    VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *)
 
 #define VMSTATE_TIMER(_f, _s)                                         \
-    VMSTATE_TIMER_V(_f, _s, 0)
+    VMSTATE_TIMER_TEST(_f, _s, NULL)
 
 #define VMSTATE_TIMER_ARRAY(_f, _s, _n)                              \
     VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
commit 639f49b60cc399d753409734b011359fb71d8f7d
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:55 2011 +0100

    vmstate: be able to store/save a pci device from a pointer
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 9df1c2c..4e09f18 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -629,6 +629,14 @@ extern const VMStateDescription vmstate_pci_device;
     .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
 }
 
+#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) {                 \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pci_device,                               \
+    .flags      = VMS_STRUCT|VMS_POINTER,                            \
+    .offset     = vmstate_offset_pointer(_state, _field, PCIDevice), \
+}
+
 extern const VMStateDescription vmstate_pcie_device;
 
 #define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
commit 6059631c042202b249d3e399741ba77afa2b555f
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:54 2011 +0100

    vmstate: Add a way to send a partial array
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index c198ce8..9df1c2c 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -429,6 +429,15 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_sub_array(_state, _field, _type, _start), \
 }
 
+#define VMSTATE_ARRAY_INT32_UNSAFE(_field, _state, _field_num, _info, _type) {\
+    .name       = (stringify(_field)),                               \
+    .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
+    .info       = &(_info),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_VARRAY_INT32,                                  \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_VARRAY_INT32(_field, _state, _field_num, _version, _info, _type) {\
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
commit 1283da72731c3704745e8dc7d6cc45f60e58556d
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:53 2011 +0100

    vmstate: add VMSTATE_STRUCT_VARRAY_UINT32
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index d801694..c198ce8 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -539,6 +539,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = offsetof(_state, _field),                          \
 }
 
+#define VMSTATE_STRUCT_VARRAY_UINT32(_field, _state, _field_num, _version, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \
+    .version_id = (_version),                                        \
+    .vmsd       = &(_vmsd),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_STRUCT|VMS_VARRAY_UINT32,                      \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
commit 15c6a56e9555dbe588a106d7891bed8ddc5b0650
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:52 2011 +0100

    vmstate: add VMSTATE_INT64_ARRAY
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 0ed63c5..d801694 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -802,6 +802,12 @@ extern const VMStateDescription vmstate_usb_device;
 #define VMSTATE_UINT32_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v)                         \
+    VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t)
+
+#define VMSTATE_INT64_ARRAY(_f, _s, _n)                               \
+    VMSTATE_INT64_ARRAY_V(_f, _s, _n, 0)
+
 #define VMSTATE_BUFFER_V(_f, _s, _v)                                  \
     VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f)))
 
commit 2a57b6c893615a587446d4c5b403fa94e8b03305
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:51 2011 +0100

    vmstate: add VMSTATE_STRUCT_VARRAY_INT32
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 6e78fa9..0ed63c5 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -529,6 +529,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_pointer(_state, _field, _type),     \
 }
 
+#define VMSTATE_STRUCT_VARRAY_INT32(_field, _state, _field_num, _version, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
+    .version_id = (_version),                                        \
+    .vmsd       = &(_vmsd),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_STRUCT|VMS_VARRAY_INT32,                       \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
commit a624b086637d5d98507ece1c41f223710af00d1f
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:50 2011 +0100

    vmstate: add UINT32 VARRAYS
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 40c6396..6e78fa9 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -299,6 +299,7 @@ enum VMStateFlags {
     VMS_VBUFFER          = 0x100,  /* Buffer with size in int32_t field */
     VMS_MULTIPLY         = 0x200,  /* multiply "size" field by field_size */
     VMS_VARRAY_UINT8     = 0x400,  /* Array with size in uint8_t field*/
+    VMS_VARRAY_UINT32    = 0x800,  /* Array with size in uint32_t field*/
 };
 
 typedef struct {
@@ -438,6 +439,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_pointer(_state, _field, _type),     \
 }
 
+#define VMSTATE_VARRAY_UINT32(_field, _state, _field_num, _version, _info, _type) {\
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
+    .info       = &(_info),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_VARRAY_UINT32|VMS_POINTER,                     \
+    .offset     = vmstate_offset_pointer(_state, _field, _type),     \
+}
+
 #define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
diff --git a/savevm.c b/savevm.c
index 4db036b..60d2f2a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1329,6 +1329,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                 n_elems = field->num;
             } else if (field->flags & VMS_VARRAY_INT32) {
                 n_elems = *(int32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT32) {
+                n_elems = *(uint32_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT16) {
                 n_elems = *(uint16_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT8) {
commit 82fa39b75181b730d6d4d09f443bd26bcfcd045c
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:49 2011 +0100

    vmstate: Fix varrays with uint8 indexes
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 0299207..40c6396 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -298,6 +298,7 @@ enum VMStateFlags {
     VMS_VARRAY_UINT16    = 0x080,  /* Array with size in uint16_t field */
     VMS_VBUFFER          = 0x100,  /* Buffer with size in int32_t field */
     VMS_MULTIPLY         = 0x200,  /* multiply "size" field by field_size */
+    VMS_VARRAY_UINT8     = 0x400,  /* Array with size in uint8_t field*/
 };
 
 typedef struct {
@@ -489,11 +490,11 @@ extern const VMStateInfo vmstate_info_unused_buffer;
 
 #define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
     .name       = (stringify(_field)),                               \
-    .num_offset = vmstate_offset_value(_state, _field_num, uint8_t),  \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
     .version_id = (_version),                                        \
     .vmsd       = &(_vmsd),                                          \
     .size       = sizeof(_type),                                     \
-    .flags      = VMS_STRUCT|VMS_VARRAY_INT32,                       \
+    .flags      = VMS_STRUCT|VMS_VARRAY_UINT8,                       \
     .offset     = offsetof(_state, _field),                          \
 }
 
diff --git a/savevm.c b/savevm.c
index ce063d1..4db036b 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1331,6 +1331,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                 n_elems = *(int32_t *)(opaque+field->num_offset);
             } else if (field->flags & VMS_VARRAY_UINT16) {
                 n_elems = *(uint16_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT8) {
+                n_elems = *(uint8_t *)(opaque+field->num_offset);
             }
             if (field->flags & VMS_POINTER) {
                 base_addr = *(void **)base_addr + field->start;
commit 9122a8fed743dbe034db53bcde4b4c313f672f2f
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Mar 10 12:33:48 2011 +0100

    vmstate: add VMSTATE_UINT32_EQUAL
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hw.h b/hw/hw.h
index 4e2d592..0299207 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -343,6 +343,7 @@ extern const VMStateInfo vmstate_info_int64;
 extern const VMStateInfo vmstate_info_uint8_equal;
 extern const VMStateInfo vmstate_info_uint16_equal;
 extern const VMStateInfo vmstate_info_int32_equal;
+extern const VMStateInfo vmstate_info_uint32_equal;
 extern const VMStateInfo vmstate_info_int32_le;
 
 extern const VMStateInfo vmstate_info_uint8;
@@ -704,6 +705,9 @@ extern const VMStateDescription vmstate_usb_device;
 #define VMSTATE_INT32_EQUAL(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_equal, int32_t)
 
+#define VMSTATE_UINT32_EQUAL(_f, _s)                                   \
+    VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint32_equal, uint32_t)
+
 #define VMSTATE_INT32_LE(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
 
diff --git a/savevm.c b/savevm.c
index a50fd31..ce063d1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -882,6 +882,27 @@ const VMStateInfo vmstate_info_uint32 = {
     .put  = put_uint32,
 };
 
+/* 32 bit uint. See that the received value is the same than the one
+   in the field */
+
+static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint32_t *v = pv;
+    uint32_t v2;
+    qemu_get_be32s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint32_equal = {
+    .name = "uint32 equal",
+    .get  = get_uint32_equal,
+    .put  = put_uint32,
+};
+
 /* 64 bit unsigned int */
 
 static int get_uint64(QEMUFile *f, void *pv, size_t size)
commit 23bfe28fffd6fff12a39c1ff7274b0dfdecbfa38
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Mar 3 21:37:55 2011 +0100

    vnc: Fix stack corruption and other bitmap related bugs
    
    Commit bc2429b9174ac2d3c56b7fd35884b0d89ec7fb02 introduced
    a severe bug (stack corruption).
    
    bitmap_clear was called with a wrong argument
    which caused out-of-bound writes to the local variable width_mask.
    
    This bug was detected with QEMU running on windows.
    It also occurs with wine:
    
    *** stack smashing detected ***:  terminated
    wine: Unhandled illegal instruction at address 0x6115c7 (thread 0009), starting debugger...
    
    The bug is not windows specific!
    
    Instead of fixing the wrong parameter value, bitmap_clear(), bitmap_set
    and width_mask were removed, and bitmap_intersect() was replaced by
    !bitmap_empty(). The new operation is much shorter and equivalent to
    the old operations.
    
    The declarations of the dirty bitmaps in vnc.h were also wrong for 64 bit
    hosts because of a rounding effect: for these hosts, VNC_MAX_WIDTH is no
    longer a multiple of (16 * BITS_PER_LONG), so the rounded value of
    VNC_DIRTY_WORDS was too small.
    
    Fix both declarations by using the macro which is designed for this
    purpose.
    
    Cc: Corentin Chary <corentincj at iksaif.net>
    Cc: Wen Congyang <wency at cn.fujitsu.com>
    Cc: Gerhard Wiesinger <lists at wiesinger.com>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 610f884..34dc0cd 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2383,7 +2383,6 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     uint8_t *guest_row;
     uint8_t *server_row;
     int cmp_bytes;
-    unsigned long width_mask[VNC_DIRTY_WORDS];
     VncState *vs;
     int has_dirty = 0;
 
@@ -2399,14 +2398,11 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
      * Check and copy modified bits from guest to server surface.
      * Update server dirty map.
      */
-    bitmap_set(width_mask, 0, (ds_get_width(vd->ds) / 16));
-    bitmap_clear(width_mask, (ds_get_width(vd->ds) / 16),
-                 VNC_DIRTY_WORDS * BITS_PER_LONG);
     cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
     guest_row  = vd->guest.ds->data;
     server_row = vd->server->data;
     for (y = 0; y < vd->guest.ds->height; y++) {
-        if (bitmap_intersects(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
+        if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) {
             int x;
             uint8_t *guest_ptr;
             uint8_t *server_ptr;
diff --git a/ui/vnc.h b/ui/vnc.h
index 8a1e7b9..f10c5dc 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -79,9 +79,12 @@ typedef void VncSendHextileTile(VncState *vs,
                                 void *last_fg,
                                 int *has_bg, int *has_fg);
 
+/* VNC_MAX_WIDTH must be a multiple of 16. */
 #define VNC_MAX_WIDTH 2560
 #define VNC_MAX_HEIGHT 2048
-#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * BITS_PER_LONG))
+
+/* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */
+#define VNC_DIRTY_BITS (VNC_MAX_WIDTH / 16)
 
 #define VNC_STAT_RECT  64
 #define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT)
@@ -114,7 +117,7 @@ typedef struct VncRectStat VncRectStat;
 struct VncSurface
 {
     struct timeval last_freq_check;
-    unsigned long dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
     VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
     DisplaySurface *ds;
 };
@@ -234,7 +237,7 @@ struct VncState
     int csock;
 
     DisplayState *ds;
-    unsigned long dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS);
     uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in
                            * vnc-jobs-async.c */
 
commit 2ea720dba50a4e95a641dd69b0a9864b315868c2
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Mar 9 16:54:34 2011 +0100

    hmp-commands.hx: fix badly merged client_migrate_info command
    
    client_migrate_info was merged badly, placing it between the command
    and the documentation for another command. In addition it did not
    respect the general rule of hmp-commands.hx, of having command
    definition before the documentation.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 372bef4..834e6a8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -821,16 +821,12 @@ Set maximum tolerated downtime (in seconds) for migration.
 ETEXI
 
     {
-        .name       = "snapshot_blkdev",
-        .args_type  = "device:B,snapshot_file:s?,format:s?",
-        .params     = "device [new-image-file] [format]",
-        .help       = "initiates a live snapshot\n\t\t\t"
-                      "of device. If a new image file is specified, the\n\t\t\t"
-                      "new image file will become the new root image.\n\t\t\t"
-                      "If format is specified, the snapshot file will\n\t\t\t"
-                      "be created in that format. Otherwise the\n\t\t\t"
-                      "snapshot will be internal! (currently unsupported)",
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .name       = "client_migrate_info",
+        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+        .params     = "protocol hostname port tls-port cert-subject",
+        .help       = "send migration info to spice/vnc client",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = client_migrate_info,
     },
 
 STEXI
@@ -842,12 +838,16 @@ new parameters (if specified) once the vm migration finished successfully.
 ETEXI
 
     {
-        .name       = "client_migrate_info",
-        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
-        .params     = "protocol hostname port tls-port cert-subject",
-        .help       = "send migration info to spice/vnc client",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = client_migrate_info,
+        .name       = "snapshot_blkdev",
+        .args_type  = "device:B,snapshot_file:s?,format:s?",
+        .params     = "device [new-image-file] [format]",
+        .help       = "initiates a live snapshot\n\t\t\t"
+                      "of device. If a new image file is specified, the\n\t\t\t"
+                      "new image file will become the new root image.\n\t\t\t"
+                      "If format is specified, the snapshot file will\n\t\t\t"
+                      "be created in that format. Otherwise the\n\t\t\t"
+                      "snapshot will be internal! (currently unsupported)",
+        .mhandler.cmd_new = do_snapshot_blkdev,
     },
 
 STEXI
commit 7d82af38b78305155553013c6fd709dc50404199
Author: Vincent Palatin <vpalatin at chromium.org>
Date:   Thu Mar 10 15:47:46 2011 -0500

    Fix performance regression in qemu_get_ram_ptr
    
    When the commit f471a17e9d869df3c6573f7ec02c4725676d6f3a converted the
    ram_blocks structure to QLIST, it also removed the conditional check before
    switching the current block at the beginning of the list.
    
    In the common use case where ram_blocks has a few blocks with only one
    frequently accessed (the main RAM), this has a performance impact as it
    performs the useless list operations on each call (which are on a really
    hot path).
    
    On my machine emulation (ARM on amd64), this patch reduces the
    percentage of CPU time spent in qemu_get_ram_ptr from 6.3% to 2.1% in the
    profiling of a full boot.
    
    Signed-off-by: Vincent Palatin <vpalatin at chromium.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index d611100..81f08b7 100644
--- a/exec.c
+++ b/exec.c
@@ -2957,8 +2957,11 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (addr - block->offset < block->length) {
-            QLIST_REMOVE(block, next);
-            QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
+            /* Move this entry to to start of the list.  */
+            if (block != QLIST_FIRST(&ram_list.blocks)) {
+                QLIST_REMOVE(block, next);
+                QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
+            }
             return block->host + (addr - block->offset);
         }
     }
commit d48751ed4f8368d3fdca99fbcd241d9efeedccbc
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date:   Thu Mar 10 09:16:52 2011 +0100

    xilinx-ethlite: Simplify byteswapping to/from brams
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 54b57d7..f35ba84 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -90,13 +90,8 @@ static uint32_t eth_readl (void *opaque, target_phys_addr_t addr)
             D(qemu_log("%s %x=%x\n", __func__, addr * 4, r));
             break;
 
-        /* Rx packet data is endian fixed at the way into the rx rams. This
-         * speeds things up because the ethlite MAC does not have a len
-         * register. That means the CPU will issue MMIO reads for the entire
-         * 2k rx buffer even for small packets.
-         */
         default:
-            r = s->regs[addr];
+            r = tswap32(s->regs[addr]);
             break;
     }
     return r;
@@ -145,9 +140,8 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
             s->regs[addr] = value;
             break;
 
-        /* Packet data, make sure it stays BE.  */
         default:
-            s->regs[addr] = cpu_to_be32(value);
+            s->regs[addr] = tswap32(value);
             break;
     }
 }
@@ -172,7 +166,6 @@ static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
     struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque;
     unsigned int rxbase = s->rxbuf * (0x800 / 4);
-    int i;
 
     /* DA filter.  */
     if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
@@ -186,12 +179,6 @@ static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
     D(qemu_log("%s %d rxbase=%x\n", __func__, size, rxbase));
     memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
 
-    /* Bring it into host endianess.  */
-    for (i = 0; i < ((size + 3) / 4); i++) {
-       uint32_t d = s->regs[rxbase + R_RX_BUF0 + i];
-       s->regs[rxbase + R_RX_BUF0 + i] = be32_to_cpu(d);
-    }
-
     s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
     if (s->regs[rxbase + R_RX_CTRL0] & CTRL_I)
         eth_pulse_irq(s);
commit b651fc6fd89365d0cdeb923e69be5611c43cbbe8
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Mar 4 03:54:59 2011 +0300

    mainstone: PCMCIA support
    
    Extend mst_fpga and mainstone with logic to support PCMCIA
    attachment (IRQs, status regs).
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/mainstone.c b/hw/mainstone.c
index 8970dd8..50691ca 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -149,6 +149,13 @@ static void mainstone_common_init(ram_addr_t ram_size,
     /* MMC/SD host */
     pxa2xx_mmci_handlers(cpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
 
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+            qdev_get_gpio_in(mst_irq, S0_IRQ),
+            qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+            qdev_get_gpio_in(mst_irq, S1_IRQ),
+            qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
+
     smc91c111_init(&nd_table[0], MST_ETH_PHYS,
                     qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
 
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 407bac9..a04355c 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -26,6 +26,12 @@
 #define MST_PCMCIA0		0xe0
 #define MST_PCMCIA1		0xe4
 
+#define MST_PCMCIAx_READY	(1 << 10)
+#define MST_PCMCIAx_nCD		(1 << 5)
+
+#define MST_PCMCIA_CD0_IRQ	9
+#define MST_PCMCIA_CD1_IRQ	13
+
 typedef struct mst_irq_state{
 	SysBusDevice busdev;
 
@@ -57,6 +63,21 @@ mst_fpga_set_irq(void *opaque, int irq, int level)
 	else
 		s->prev_level &= ~(1u << irq);
 
+	switch(irq) {
+	case MST_PCMCIA_CD0_IRQ:
+		if (level)
+			s->pcmcia0 &= ~MST_PCMCIAx_nCD;
+		else
+			s->pcmcia0 |=  MST_PCMCIAx_nCD;
+		break;
+	case MST_PCMCIA_CD1_IRQ:
+		if (level)
+			s->pcmcia1 &= ~MST_PCMCIAx_nCD;
+		else
+			s->pcmcia1 |=  MST_PCMCIAx_nCD;
+		break;
+	}
+
 	if ((s->intmskena & (1u << irq)) && level)
 		s->intsetclr |= 1u << irq;
 
@@ -141,11 +162,12 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 		s->intsetclr = (value & 0xFEEFF);
 		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
 		break;
+		/* For PCMCIAx allow the to change only power and reset */
 	case MST_PCMCIA0:
-		s->pcmcia0 = value;
+		s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
 		break;
 	case MST_PCMCIA1:
-		s->pcmcia1 = value;
+		s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
 		break;
 	default:
 		printf("Mainstone - mst_fpga_writeb: Bad register offset "
@@ -180,6 +202,9 @@ static int mst_fpga_init(SysBusDevice *dev)
 
 	s = FROM_SYSBUS(mst_irq_state, dev);
 
+	s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
+	s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
+
 	sysbus_init_irq(dev, &s->parent);
 
 	/* alloc the external 16 irqs */
commit 95499a1d28f1f6255d7d74d2aaeaa2e7447b2b26
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Mar 4 03:54:58 2011 +0300

    mainstone: use gpio 0 for connection of FPGA instead of hooking into PIC directly
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/mainstone.c b/hw/mainstone.c
index 4eabdb9..8970dd8 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -140,7 +140,7 @@ static void mainstone_common_init(ram_addr_t ram_size,
     }
 
     mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
-                    qdev_get_gpio_in(cpu->pic, PXA2XX_PIC_GPIO_0));
+                    qdev_get_gpio_in(cpu->gpio, 0));
 
     /* setup keypad */
     printf("map addr %p\n", &map);
commit 8034ce7d1702d0bfa85618d345e2db0644048bc7
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Mar 10 03:31:02 2011 +0100

    pxa2xx_timer: Get rid of .level in PXA2xxTimer0.

diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index effe653..1242f82 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -64,7 +64,6 @@ typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
 
 typedef struct {
     uint32_t value;
-    int level;
     qemu_irq irq;
     QEMUTimer *qtimer;
     int num;
@@ -278,20 +277,13 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
         s->irq_enabled = value & 0xfff;
         break;
     case OSSR:	/* Status register */
+        value &= s->events;
         s->events &= ~value;
-        for (i = 0; i < 4; i ++, value >>= 1) {
-            if (s->timer[i].level && (value & 1)) {
-                s->timer[i].level = 0;
+        for (i = 0; i < 4; i ++, value >>= 1)
+            if (value & 1)
                 qemu_irq_lower(s->timer[i].irq);
-            }
-        }
-        if (pxa2xx_timer_has_tm4(s)) {
-            for (i = 0; i < 8; i ++, value >>= 1)
-                if (s->tm4[i].tm.level && (value & 1))
-                    s->tm4[i].tm.level = 0;
-            if (!(s->events & 0xff0))
-                qemu_irq_lower(s->irq4);
-        }
+        if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
+            qemu_irq_lower(s->irq4);
         break;
     case OWER:	/* XXX: Reset on OSMR3 match? */
         s->reset3 = value;
@@ -351,7 +343,6 @@ static void pxa2xx_timer_tick(void *opaque)
     PXA2xxTimerInfo *i = t->info;
 
     if (i->irq_enabled & (1 << t->num)) {
-        t->level = 1;
         i->events |= 1 << t->num;
         qemu_irq_raise(t->irq);
     }
@@ -411,7 +402,6 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->timer[i].irq);
         s->timer[i].info = s;
         s->timer[i].num = i;
-        s->timer[i].level = 0;
         s->timer[i].qtimer = qemu_new_timer(vm_clock,
                         pxa2xx_timer_tick, &s->timer[i]);
     }
@@ -422,7 +412,6 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
             s->tm4[i].tm.value = 0;
             s->tm4[i].tm.info = s;
             s->tm4[i].tm.num = i + 4;
-            s->tm4[i].tm.level = 0;
             s->tm4[i].freq = 0;
             s->tm4[i].control = 0x0;
             s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
@@ -439,12 +428,11 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
     .name = "pxa2xx_timer0",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(value, PXA2xxTimer0),
-        VMSTATE_INT32(level, PXA2xxTimer0),
         VMSTATE_END_OF_LIST(),
     },
 };
commit 7c29d6ce0fe1486688ada09b7da22eea05e90014
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Mar 10 03:11:47 2011 +0100

    pxa2xx_pic: fixup initialisation
    
    This is based on Dmitry Eremin-Solenikov's patch but simplified.

diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 86c0ee6..e9a5361 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -268,12 +268,11 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 
     qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-
     /* Enable IC memory-mapped registers access.  */
     iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
                     pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(sysbus_from_qdev(dev), 0x00100000, iomemtype);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
commit 4ff927cc62ea79092e21827f17d19a3d85973e84
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Mar 4 03:40:59 2011 +0300

    pxa2xx_timer: separate irq for pxa27x handling
    
    First, sysbus_init_irq shan't be called on on-stack variables. Indeed,
    it only stores a passed pointer in qdev and the stored irq is later
    populated, so we get a nice write-to-stack bug.
    Second, irq for pxa27x should probably be handled in a more gentler way,
    as we should check if we have events to raise this irq.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 0fbd4a8..effe653 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -94,6 +94,7 @@ struct PXA2xxTimerInfo {
     uint32_t reset3;
     uint32_t snapshot;
 
+    qemu_irq irq4;
     PXA2xxTimer4 tm4[8];
 };
 
@@ -289,7 +290,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                 if (s->tm4[i].tm.level && (value & 1))
                     s->tm4[i].tm.level = 0;
             if (!(s->events & 0xff0))
-                qemu_irq_lower(s->tm4->tm.irq);
+                qemu_irq_lower(s->irq4);
         }
         break;
     case OWER:	/* XXX: Reset on OSMR3 match? */
@@ -372,6 +373,8 @@ static void pxa2xx_timer_tick4(void *opaque)
         t->clock = 0;
     if (t->control & (1 << 6))
         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
+    if (i->events & 0xff0)
+        qemu_irq_raise(i->irq4);
 }
 
 static int pxa25x_timer_post_load(void *opaque, int version_id)
@@ -395,7 +398,6 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
     int i;
     int iomemtype;
     PXA2xxTimerInfo *s;
-    qemu_irq irq4;
 
     s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
     s->irq_enabled = 0;
@@ -414,7 +416,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
                         pxa2xx_timer_tick, &s->timer[i]);
     }
     if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
-        sysbus_init_irq(dev, &irq4);
+        sysbus_init_irq(dev, &s->irq4);
 
         for (i = 0; i < 8; i ++) {
             s->tm4[i].tm.value = 0;
@@ -425,7 +427,6 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
             s->tm4[i].control = 0x0;
             s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
                         pxa2xx_timer_tick4, &s->tm4[i]);
-            s->tm4[i].tm.irq = irq4;
         }
     }
 
commit ddca9fb2b5ecc7ccaa81fbc73d2b723922c181f1
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 7 08:06:10 2011 +0000

    trace: Trace posix-aio-compat.c completion and cancellation
    
    This patch adds paio_complete() and paio_cancel() trace events to
    complement the paio_submit() event.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index fa5494d..6d4df9d 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -455,6 +455,9 @@ static int posix_aio_process_queue(void *opaque)
                 } else {
                     ret = -ret;
                 }
+
+                trace_paio_complete(acb, acb->common.opaque, ret);
+
                 /* remove the request */
                 *pacb = acb->next;
                 /* call the callback */
@@ -537,6 +540,8 @@ static void paio_cancel(BlockDriverAIOCB *blockacb)
     struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb;
     int active = 0;
 
+    trace_paio_cancel(acb, acb->common.opaque);
+
     mutex_lock(&lock);
     if (!acb->active) {
         QTAILQ_REMOVE(&request_list, acb, node);
diff --git a/trace-events b/trace-events
index 0a26d6a..90c9e0b 100644
--- a/trace-events
+++ b/trace-events
@@ -62,6 +62,8 @@ disable virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "re
 
 # posix-aio-compat.c
 disable paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d"
+disable paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d"
+disable paio_cancel(void *acb, void *opaque) "acb %p opaque %p"
 
 # ioport.c
 disable cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u"
commit a13aac04e13b246edab6c0c08513504ecb71bbd4
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Mar 7 07:58:04 2011 +0000

    trace: Trace bdrv_aio_flush()
    
    Add a trace event for bdrv_aio_flush() to complement the existing
    bdrv_aio_readv() and bdrv_aio_writev() events.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block.c b/block.c
index f7d91a2..0559d83 100644
--- a/block.c
+++ b/block.c
@@ -2477,6 +2477,8 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
 {
     BlockDriver *drv = bs->drv;
 
+    trace_bdrv_aio_flush(bs, opaque);
+
     if (bs->open_flags & BDRV_O_NO_FLUSH) {
         return bdrv_aio_noop_em(bs, cb, opaque);
     }
diff --git a/trace-events b/trace-events
index c791719..0a26d6a 100644
--- a/trace-events
+++ b/trace-events
@@ -51,6 +51,7 @@ disable multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
 disable bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
 disable bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p"
 disable bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d"
+disable bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
 disable bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 
commit 0b5538c300a56c3cfb33022840fe0b4968147e7a
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Feb 26 18:38:39 2011 +0000

    simpletrace: Thread-safe tracing
    
    Trace events outside the global mutex cannot be used with the simple
    trace backend since it is not thread-safe.  There is no check to prevent
    them being enabled so people sometimes learn this the hard way.
    
    This patch restructures the simple trace backend with a ring buffer
    suitable for multiple concurrent writers.  A writeout thread empties the
    trace buffer when threshold fill levels are reached.  Should the
    writeout thread be unable to keep up with trace generation, records will
    simply be dropped.
    
    Each time events are dropped a special record is written to the trace
    file indicating how many events were dropped.  The event ID is
    0xfffffffffffffffe and its signature is dropped(uint32_t count).
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index a6cc56f..f15069c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -141,11 +141,6 @@ source tree.  It may not be as powerful as platform-specific or third-party
 trace backends but it is portable.  This is the recommended trace backend
 unless you have specific needs for more advanced backends.
 
-Warning: the "simple" backend is not thread-safe so only enable trace events
-that are executed while the global mutex is held.  Much of QEMU meets this
-requirement but some utility functions like qemu_malloc() or thread-related
-code cannot be safely traced using the "simple" backend.
-
 ==== Monitor commands ====
 
 * info trace
diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index 9fe3dda..2ad5699 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -16,6 +16,7 @@ import inspect
 header_event_id = 0xffffffffffffffff
 header_magic    = 0xf2b177cb0aa429b4
 header_version  = 0
+dropped_event_id = 0xfffffffffffffffe
 
 trace_fmt = '=QQQQQQQQ'
 trace_len = struct.calcsize(trace_fmt)
@@ -28,7 +29,7 @@ def parse_events(fobj):
         """Extract argument names from a parameter list."""
         return tuple(arg.split()[-1].lstrip('*') for arg in args.split(','))
 
-    events = {}
+    events = {dropped_event_id: ('dropped', 'count')}
     event_num = 0
     for line in fobj:
         m = event_re.match(line.strip())
diff --git a/simpletrace.c b/simpletrace.c
index 9ea0d1f..9926ab3 100644
--- a/simpletrace.c
+++ b/simpletrace.c
@@ -12,6 +12,9 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <time.h>
+#include <signal.h>
+#include <pthread.h>
+#include "qerror.h"
 #include "qemu-timer.h"
 #include "trace.h"
 
@@ -24,6 +27,12 @@
 /** Trace file version number, bump if format changes */
 #define HEADER_VERSION 0
 
+/** Records were dropped event ID */
+#define DROPPED_EVENT_ID (~(uint64_t)0 - 1)
+
+/** Trace record is valid */
+#define TRACE_RECORD_VALID ((uint64_t)1 << 63)
+
 /** Trace buffer entry */
 typedef struct {
     uint64_t event;
@@ -37,126 +46,135 @@ typedef struct {
 } TraceRecord;
 
 enum {
-    TRACE_BUF_LEN = 64 * 1024 / sizeof(TraceRecord),
+    TRACE_BUF_LEN = 4096,
+    TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4,
 };
 
+/*
+ * Trace records are written out by a dedicated thread.  The thread waits for
+ * records to become available, writes them out, and then waits again.
+ */
+static pthread_mutex_t trace_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t trace_available_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t trace_empty_cond = PTHREAD_COND_INITIALIZER;
+static bool trace_available;
+static bool trace_writeout_enabled;
+
 static TraceRecord trace_buf[TRACE_BUF_LEN];
 static unsigned int trace_idx;
 static FILE *trace_fp;
 static char *trace_file_name = NULL;
-static bool trace_file_enabled = false;
-
-void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
-{
-    stream_printf(stream, "Trace file \"%s\" %s.\n",
-                  trace_file_name, trace_file_enabled ? "on" : "off");
-}
-
-static bool write_header(FILE *fp)
-{
-    static const TraceRecord header = {
-        .event = HEADER_EVENT_ID,
-        .timestamp_ns = HEADER_MAGIC,
-        .x1 = HEADER_VERSION,
-    };
-
-    return fwrite(&header, sizeof header, 1, fp) == 1;
-}
 
 /**
- * set_trace_file : To set the name of a trace file.
- * @file : pointer to the name to be set.
- *         If NULL, set to the default name-<pid> set at config time.
+ * Read a trace record from the trace buffer
+ *
+ * @idx         Trace buffer index
+ * @record      Trace record to fill
+ *
+ * Returns false if the record is not valid.
  */
-bool st_set_trace_file(const char *file)
+static bool get_trace_record(unsigned int idx, TraceRecord *record)
 {
-    st_set_trace_file_enabled(false);
-
-    free(trace_file_name);
-
-    if (!file) {
-        if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) {
-            trace_file_name = NULL;
-            return false;
-        }
-    } else {
-        if (asprintf(&trace_file_name, "%s", file) < 0) {
-            trace_file_name = NULL;
-            return false;
-        }
+    if (!(trace_buf[idx].event & TRACE_RECORD_VALID)) {
+        return false;
     }
 
-    st_set_trace_file_enabled(true);
+    __sync_synchronize(); /* read memory barrier before accessing record */
+
+    *record = trace_buf[idx];
+    record->event &= ~TRACE_RECORD_VALID;
     return true;
 }
 
-static void flush_trace_file(void)
+/**
+ * Kick writeout thread
+ *
+ * @wait        Whether to wait for writeout thread to complete
+ */
+static void flush_trace_file(bool wait)
 {
-    /* If the trace file is not open yet, open it now */
-    if (!trace_fp) {
-        trace_fp = fopen(trace_file_name, "w");
-        if (!trace_fp) {
-            /* Avoid repeatedly trying to open file on failure */
-            trace_file_enabled = false;
-            return;
-        }
-        write_header(trace_fp);
-    }
+    pthread_mutex_lock(&trace_lock);
+    trace_available = true;
+    pthread_cond_signal(&trace_available_cond);
 
-    if (trace_fp) {
-        size_t unused; /* for when fwrite(3) is declared warn_unused_result */
-        unused = fwrite(trace_buf, trace_idx * sizeof(trace_buf[0]), 1, trace_fp);
+    if (wait) {
+        pthread_cond_wait(&trace_empty_cond, &trace_lock);
     }
+
+    pthread_mutex_unlock(&trace_lock);
 }
 
-void st_flush_trace_buffer(void)
+static void wait_for_trace_records_available(void)
 {
-    if (trace_file_enabled) {
-        flush_trace_file();
+    pthread_mutex_lock(&trace_lock);
+    while (!(trace_available && trace_writeout_enabled)) {
+        pthread_cond_signal(&trace_empty_cond);
+        pthread_cond_wait(&trace_available_cond, &trace_lock);
     }
-
-    /* Discard written trace records */
-    trace_idx = 0;
+    trace_available = false;
+    pthread_mutex_unlock(&trace_lock);
 }
 
-void st_set_trace_file_enabled(bool enable)
+static void *writeout_thread(void *opaque)
 {
-    if (enable == trace_file_enabled) {
-        return; /* no change */
-    }
+    TraceRecord record;
+    unsigned int writeout_idx = 0;
+    unsigned int num_available, idx;
+    size_t unused;
+
+    for (;;) {
+        wait_for_trace_records_available();
+
+        num_available = trace_idx - writeout_idx;
+        if (num_available > TRACE_BUF_LEN) {
+            record = (TraceRecord){
+                .event = DROPPED_EVENT_ID,
+                .x1 = num_available,
+            };
+            unused = fwrite(&record, sizeof(record), 1, trace_fp);
+            writeout_idx += num_available;
+        }
 
-    /* Flush/discard trace buffer */
-    st_flush_trace_buffer();
+        idx = writeout_idx % TRACE_BUF_LEN;
+        while (get_trace_record(idx, &record)) {
+            trace_buf[idx].event = 0; /* clear valid bit */
+            unused = fwrite(&record, sizeof(record), 1, trace_fp);
+            idx = ++writeout_idx % TRACE_BUF_LEN;
+        }
 
-    /* To disable, close trace file */
-    if (!enable) {
-        fclose(trace_fp);
-        trace_fp = NULL;
+        fflush(trace_fp);
     }
-
-    trace_file_enabled = enable;
+    return NULL;
 }
 
 static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
                   uint64_t x4, uint64_t x5, uint64_t x6)
 {
-    TraceRecord *rec = &trace_buf[trace_idx];
+    unsigned int idx;
+    uint64_t timestamp;
 
     if (!trace_list[event].state) {
         return;
     }
 
-    rec->event = event;
-    rec->timestamp_ns = get_clock();
-    rec->x1 = x1;
-    rec->x2 = x2;
-    rec->x3 = x3;
-    rec->x4 = x4;
-    rec->x5 = x5;
-    rec->x6 = x6;
-
-    if (++trace_idx == TRACE_BUF_LEN) {
-        st_flush_trace_buffer();
+    timestamp = get_clock();
+
+    idx = __sync_fetch_and_add(&trace_idx, 1) % TRACE_BUF_LEN;
+    trace_buf[idx] = (TraceRecord){
+        .event = event,
+        .timestamp_ns = timestamp,
+        .x1 = x1,
+        .x2 = x2,
+        .x3 = x3,
+        .x4 = x4,
+        .x5 = x5,
+        .x6 = x6,
+    };
+    __sync_synchronize(); /* write barrier before marking as valid */
+    trace_buf[idx].event |= TRACE_RECORD_VALID;
+
+    if ((idx + 1) % TRACE_BUF_FLUSH_THRESHOLD == 0) {
+        flush_trace_file(false);
     }
 }
 
@@ -195,24 +213,93 @@ void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t
     trace(event, x1, x2, x3, x4, x5, x6);
 }
 
+void st_set_trace_file_enabled(bool enable)
+{
+    if (enable == !!trace_fp) {
+        return; /* no change */
+    }
+
+    /* Halt trace writeout */
+    flush_trace_file(true);
+    trace_writeout_enabled = false;
+    flush_trace_file(true);
+
+    if (enable) {
+        static const TraceRecord header = {
+            .event = HEADER_EVENT_ID,
+            .timestamp_ns = HEADER_MAGIC,
+            .x1 = HEADER_VERSION,
+        };
+
+        trace_fp = fopen(trace_file_name, "w");
+        if (!trace_fp) {
+            return;
+        }
+
+        if (fwrite(&header, sizeof header, 1, trace_fp) != 1) {
+            fclose(trace_fp);
+            trace_fp = NULL;
+            return;
+        }
+
+        /* Resume trace writeout */
+        trace_writeout_enabled = true;
+        flush_trace_file(false);
+    } else {
+        fclose(trace_fp);
+        trace_fp = NULL;
+    }
+}
+
 /**
- * Flush the trace buffer on exit
+ * Set the name of a trace file
+ *
+ * @file        The trace file name or NULL for the default name-<pid> set at
+ *              config time
  */
-static void __attribute__((constructor)) st_init(void)
+bool st_set_trace_file(const char *file)
 {
-    atexit(st_flush_trace_buffer);
+    st_set_trace_file_enabled(false);
+
+    free(trace_file_name);
+
+    if (!file) {
+        if (asprintf(&trace_file_name, CONFIG_TRACE_FILE, getpid()) < 0) {
+            trace_file_name = NULL;
+            return false;
+        }
+    } else {
+        if (asprintf(&trace_file_name, "%s", file) < 0) {
+            trace_file_name = NULL;
+            return false;
+        }
+    }
+
+    st_set_trace_file_enabled(true);
+    return true;
+}
+
+void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
+{
+    stream_printf(stream, "Trace file \"%s\" %s.\n",
+                  trace_file_name, trace_fp ? "on" : "off");
 }
 
 void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
 {
     unsigned int i;
 
-    for (i = 0; i < trace_idx; i++) {
+    for (i = 0; i < TRACE_BUF_LEN; i++) {
+        TraceRecord record;
+
+        if (!get_trace_record(i, &record)) {
+            continue;
+        }
         stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64
                       " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n",
-                      trace_buf[i].event, trace_buf[i].x1, trace_buf[i].x2,
-                      trace_buf[i].x3, trace_buf[i].x4, trace_buf[i].x5,
-                      trace_buf[i].x6);
+                      record.event, record.x1, record.x2,
+                      record.x3, record.x4, record.x5,
+                      record.x6);
     }
 }
 
@@ -226,30 +313,44 @@ void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, cons
     }
 }
 
-static TraceEvent* find_trace_event_by_name(const char *tname)
+bool st_change_trace_event_state(const char *name, bool enabled)
 {
     unsigned int i;
 
-    if (!tname) {
-        return NULL;
-    }
-
     for (i = 0; i < NR_TRACE_EVENTS; i++) {
-        if (!strcmp(trace_list[i].tp_name, tname)) {
-            return &trace_list[i];
+        if (!strcmp(trace_list[i].tp_name, name)) {
+            trace_list[i].state = enabled;
+            return true;
         }
     }
-    return NULL; /* indicates end of list reached without a match */
+    return false;
+}
+
+void st_flush_trace_buffer(void)
+{
+    flush_trace_file(true);
 }
 
-bool st_change_trace_event_state(const char *tname, bool tstate)
+void st_init(const char *file)
 {
-    TraceEvent *tp;
+    pthread_t thread;
+    pthread_attr_t attr;
+    sigset_t set, oldset;
+    int ret;
+
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-    tp = find_trace_event_by_name(tname);
-    if (tp) {
-        tp->state = tstate;
-        return true;
+    sigfillset(&set);
+    pthread_sigmask(SIG_SETMASK, &set, &oldset);
+    ret = pthread_create(&thread, &attr, writeout_thread, NULL);
+    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
+    if (ret != 0) {
+        error_report("warning: unable to create trace file thread\n");
+        return;
     }
-    return false;
+
+    atexit(st_flush_trace_buffer);
+    st_set_trace_file(file);
 }
diff --git a/simpletrace.h b/simpletrace.h
index 2f44ed3..3a5bd9f 100644
--- a/simpletrace.h
+++ b/simpletrace.h
@@ -15,6 +15,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 
+#ifdef CONFIG_SIMPLE_TRACE
 typedef uint64_t TraceEventID;
 
 typedef struct {
@@ -36,5 +37,12 @@ void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
 void st_set_trace_file_enabled(bool enable);
 bool st_set_trace_file(const char *file);
 void st_flush_trace_buffer(void);
+void st_init(const char *file);
+#else
+static inline void st_init(const char *file)
+{
+    /* Do nothing */
+}
+#endif /* !CONFIG_SIMPLE_TRACE */
 
 #endif /* SIMPLETRACE_H */
diff --git a/vl.c b/vl.c
index b436952..5e007a7 100644
--- a/vl.c
+++ b/vl.c
@@ -47,9 +47,6 @@
 #include <dirent.h>
 #include <netdb.h>
 #include <sys/select.h>
-#ifdef CONFIG_SIMPLE_TRACE
-#include "trace.h"
-#endif
 
 #ifdef CONFIG_BSD
 #include <sys/stat.h>
@@ -159,6 +156,7 @@ int main(int argc, char **argv)
 #include "slirp/libslirp.h"
 
 #include "trace.h"
+#include "simpletrace.h"
 #include "qemu-queue.h"
 #include "cpus.h"
 #include "arch_init.h"
@@ -1941,10 +1939,8 @@ int main(int argc, char **argv, char **envp)
     const char *incoming = NULL;
     int show_vnc_port = 0;
     int defconfig = 1;
-
-#ifdef CONFIG_SIMPLE_TRACE
     const char *trace_file = NULL;
-#endif
+
     atexit(qemu_run_exit_notifiers);
     error_set_progname(argv[0]);
 
@@ -2770,6 +2766,8 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();
 
+    st_init(trace_file);
+
     /* If no data_dir is specified then try to find it relative to the
        executable path.  */
     if (!data_dir) {
@@ -2780,12 +2778,6 @@ int main(int argc, char **argv, char **envp)
         data_dir = CONFIG_QEMU_DATADIR;
     }
 
-#ifdef CONFIG_SIMPLE_TRACE
-    /*
-     * Set the trace file name, if specified.
-     */
-    st_set_trace_file(trace_file);
-#endif
     /*
      * Default to max_cpus = smp_cpus, in case the user doesn't
      * specify a max_cpus value.
commit 07bf23a77131668ef8db37e08d508b117655ce86
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:18 2011 +0100

    MAINTAINERS: add LatticeMico32 maintainer
    
    Add me as the lm32-target and machines maintainer.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index ab48380..9f3ff0e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -70,6 +70,11 @@ M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
 S: Maintained
 F: target-cris/
 
+LM32
+M: Michael Walle <michael at walle.cc>
+S: Maintained
+F: target-lm32/
+
 M68K
 M: Paul Brook <paul at codesourcery.com>
 S: Maintained
@@ -202,6 +207,13 @@ M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
 S: Maintained
 F: hw/etraxfs.c
 
+LM32 Machines
+-------------
+EVR32 and uclinux BSP
+M: Michael Walle <michael at walle.cc>
+S: Maintained
+F: hw/lm32_boards.c
+
 M68K Machines
 -------------
 an5206
commit 613a22c931f15d61d92e45a76126f9f0f8b76121
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:17 2011 +0100

    Add lm32 target to configure
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/configure b/configure
index ef51a58..5513d3e 100755
--- a/configure
+++ b/configure
@@ -280,7 +280,7 @@ else
 fi
 
 case "$cpu" in
-  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
+  alpha|cris|ia64|lm32|m68k|microblaze|ppc|ppc64|sparc64)
     cpu="$cpu"
   ;;
   i386|i486|i586|i686|i86pc|BePC)
@@ -982,6 +982,7 @@ i386-softmmu \
 x86_64-softmmu \
 arm-softmmu \
 cris-softmmu \
+lm32-softmmu \
 m68k-softmmu \
 microblaze-softmmu \
 microblazeel-softmmu \
@@ -2552,7 +2553,7 @@ echo "docdir=$docdir" >> $config_host_mak
 echo "confdir=$confdir" >> $config_host_mak
 
 case "$cpu" in
-  i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
+  i386|x86_64|alpha|cris|hppa|ia64|lm32|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
     ARCH=$cpu
   ;;
   armv4b|armv4l)
@@ -2908,7 +2909,7 @@ target_arch2=`echo $target | cut -d '-' -f 1`
 target_bigendian="no"
 
 case "$target_arch2" in
-  armeb|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus)
+  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus)
   target_bigendian=yes
   ;;
 esac
@@ -3003,6 +3004,9 @@ case "$target_arch2" in
     target_nptl="yes"
     target_phys_bits=32
   ;;
+  lm32)
+    target_phys_bits=32
+  ;;
   m68k)
     bflt="yes"
     gdb_xml_files="cf-core.xml cf-fp.xml"
commit d65f083146d269b48d53368a8e49aa7d2d4a08fd
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:16 2011 +0100

    lm32: opcode testsuite
    
    This patch creates tests/lm32 directory and adds tests for every
    LatticeMico32 opcode.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/tests/Makefile b/tests/Makefile
index 9ded4b7..430e0c1 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -142,6 +142,10 @@ hello-mipsel: hello-mips.c
 test-cris:
 	$(MAKE) -C cris check
 
+# testsuite for the LM32 port.
+test-lm32:
+	$(MAKE) -C lm32 check
+
 clean:
 	rm -f *~ *.o test-i386.out test-i386.ref \
            test-x86_64.log test-x86_64.ref qruncom $(TESTS)
diff --git a/tests/lm32/Makefile b/tests/lm32/Makefile
new file mode 100644
index 0000000..03a1abb
--- /dev/null
+++ b/tests/lm32/Makefile
@@ -0,0 +1,102 @@
+-include ../../config-host.mak
+
+CROSS=lm32-elf-
+
+SIM = qemu-system-lm32
+SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
+
+CC      = $(CROSS)gcc
+AS      = $(CROSS)as
+AS      = $(CC) -x assembler
+SIZE    = $(CROSS)size
+LD      = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+LDFLAGS = -Tlinker.ld
+
+CRT        = crt.o
+TESTCASES += test_add.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_and.tst
+TESTCASES += test_andhi.tst
+TESTCASES += test_andi.tst
+TESTCASES += test_b.tst
+TESTCASES += test_be.tst
+TESTCASES += test_bg.tst
+TESTCASES += test_bge.tst
+TESTCASES += test_bgeu.tst
+TESTCASES += test_bgu.tst
+TESTCASES += test_bi.tst
+TESTCASES += test_bne.tst
+TESTCASES += test_break.tst
+TESTCASES += test_bret.tst
+TESTCASES += test_call.tst
+TESTCASES += test_calli.tst
+TESTCASES += test_cmpe.tst
+TESTCASES += test_cmpei.tst
+TESTCASES += test_cmpg.tst
+TESTCASES += test_cmpgi.tst
+TESTCASES += test_cmpge.tst
+TESTCASES += test_cmpgei.tst
+TESTCASES += test_cmpgeu.tst
+TESTCASES += test_cmpgeui.tst
+TESTCASES += test_cmpgu.tst
+TESTCASES += test_cmpgui.tst
+TESTCASES += test_cmpne.tst
+TESTCASES += test_cmpnei.tst
+TESTCASES += test_divu.tst
+TESTCASES += test_eret.tst
+TESTCASES += test_lb.tst
+TESTCASES += test_lbu.tst
+TESTCASES += test_lh.tst
+TESTCASES += test_lhu.tst
+TESTCASES += test_lw.tst
+TESTCASES += test_modu.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_muli.tst
+TESTCASES += test_nor.tst
+TESTCASES += test_nori.tst
+TESTCASES += test_or.tst
+TESTCASES += test_ori.tst
+TESTCASES += test_orhi.tst
+#TESTCASES += test_rcsr.tst
+TESTCASES += test_ret.tst
+TESTCASES += test_sb.tst
+TESTCASES += test_scall.tst
+TESTCASES += test_sextb.tst
+TESTCASES += test_sexth.tst
+TESTCASES += test_sh.tst
+TESTCASES += test_sl.tst
+TESTCASES += test_sli.tst
+TESTCASES += test_sr.tst
+TESTCASES += test_sri.tst
+TESTCASES += test_sru.tst
+TESTCASES += test_srui.tst
+TESTCASES += test_sub.tst
+TESTCASES += test_sw.tst
+#TESTCASES += test_wcsr.tst
+TESTCASES += test_xnor.tst
+TESTCASES += test_xnori.tst
+TESTCASES += test_xor.tst
+TESTCASES += test_xori.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/lm32/%.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/lm32/%.S
+	$(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT)
+	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(CRT) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+	@for case in $(TESTCASES); do \
+		$(SIM) $(SIMFLAGS) ./$$case; \
+	done
+
+clean:
+	$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/lm32/crt.S b/tests/lm32/crt.S
new file mode 100644
index 0000000..5f9cfd9
--- /dev/null
+++ b/tests/lm32/crt.S
@@ -0,0 +1,84 @@
+.text
+.global _start
+
+_start:
+_reset_handler:
+	xor r0, r0, r0
+	mvhi r1, hi(_start)
+	ori r1, r1, lo(_start)
+	wcsr eba, r1
+	wcsr deba, r1
+	bi _main
+	nop
+	nop
+
+_breakpoint_handler:
+	ori r25, r25, 1
+	addi ra, ba, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_instruction_bus_error_handler:
+	ori r25, r25, 2
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_watchpoint_handler:
+	ori r25, r25, 4
+	addi ra, ba, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_data_bus_error_handler:
+	ori r25, r25, 8
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_divide_by_zero_handler:
+	ori r25, r25, 16
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_interrupt_handler:
+	ori r25, r25, 32
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
+_system_call_handler:
+	ori r25, r25, 64
+	addi ra, ea, 4
+	ret
+	nop
+	nop
+	nop
+	nop
+	nop
+
diff --git a/tests/lm32/linker.ld b/tests/lm32/linker.ld
new file mode 100644
index 0000000..52d43a4
--- /dev/null
+++ b/tests/lm32/linker.ld
@@ -0,0 +1,55 @@
+OUTPUT_FORMAT("elf32-lm32")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+	ram : ORIGIN = 0x08000000, LENGTH = 0x04000000  /* 64M */
+}
+
+SECTIONS
+{
+	.text :
+	{
+		_ftext = .;
+		*(.text .stub .text.* .gnu.linkonce.t.*)
+		_etext = .;
+	} > ram
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		_frodata = .;
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+		*(.rodata1)
+		_erodata = .;
+	} > ram
+
+	.data :
+	{
+		. = ALIGN(4);
+		_fdata = .;
+		*(.data .data.* .gnu.linkonce.d.*)
+		*(.data1)
+		_gp = ALIGN(16);
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
+		_edata = .;
+	} > ram
+
+	.bss :
+	{
+		. = ALIGN(4);
+		_fbss = .;
+		*(.dynsbss)
+		*(.sbss .sbss.* .gnu.linkonce.sb.*)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+		*(COMMON)
+		_ebss = .;
+		_end = .;
+	} > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+
diff --git a/tests/lm32/macros.inc b/tests/lm32/macros.inc
new file mode 100644
index 0000000..367c7c5
--- /dev/null
+++ b/tests/lm32/macros.inc
@@ -0,0 +1,79 @@
+
+.macro test_name name
+	.data
+tn_\name:
+	.asciz "\name"
+	.text
+	mvhi r13, hi(tn_\name)
+	ori r13, r13, lo(tn_\name)
+	sw (r12+8), r13
+.endm
+
+.macro load reg val
+	mvhi \reg, hi(\val)
+	ori \reg, \reg, lo(\val)
+.endm
+
+.macro tc_pass
+	mvi r13, 0
+	sw (r12+4), r13
+.endm
+
+.macro tc_fail
+	mvi r13, 1
+	sw (r12+4), r13
+.endm
+
+.macro check_r3 val
+	mvhi r13, hi(\val)
+	ori r13, r13, lo(\val)
+	be r3, r13, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro check_mem adr val
+	mvhi r13, hi(\adr)
+	ori r13, r13, lo(\adr)
+	mvhi r14, hi(\val)
+	ori r14, r14, lo(\val)
+	lw r13, (r13+0)
+	be r13, r14, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro check_excp excp
+	andi r13, r25, \excp
+	bne r13, r0, 1f
+	tc_fail
+	bi 2f
+1:
+	tc_pass
+2:
+.endm
+
+.macro start
+	.global _main
+	.text
+_main:
+	mvhi r12, hi(0xffff0000)      # base address of test block
+	ori r12, r12, lo(0xffff0000)
+.endm
+
+.macro end
+	sw (r12+0), r0
+1:
+	bi 1b
+.endm
+
+# base +
+#  0  ctrl
+#  4  pass/fail
+#  8  ptr to test name
diff --git a/tests/lm32/test_add.S b/tests/lm32/test_add.S
new file mode 100644
index 0000000..030ad19
--- /dev/null
+++ b/tests/lm32/test_add.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name ADD_1
+mvi r1, 0
+mvi r2, 0
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_2
+mvi r1, 0
+mvi r2, 1
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_3
+mvi r1, 1
+mvi r2, 0
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_4
+mvi r1, 1
+mvi r2, -1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_5
+mvi r1, -1
+mvi r2, 1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_6
+mvi r1, -1
+mvi r2, 0
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_7
+mvi r1, 0
+mvi r2, -1
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_8
+mvi r3, 2
+add r3, r3, r3
+check_r3 4
+
+test_name ADD_9
+mvi r1, 4
+mvi r3, 2
+add r3, r1, r3
+check_r3 6
+
+test_name ADD_10
+mvi r1, 4
+mvi r3, 2
+add r3, r3, r1
+check_r3 6
+
+test_name ADD_11
+mvi r1, 4
+add r3, r1, r1
+check_r3 8
+
+test_name ADD_12
+load r1 0x12345678
+load r2 0xabcdef97
+add r3, r1, r2
+check_r3 0xbe02460f
+
+end
diff --git a/tests/lm32/test_addi.S b/tests/lm32/test_addi.S
new file mode 100644
index 0000000..68e766d
--- /dev/null
+++ b/tests/lm32/test_addi.S
@@ -0,0 +1,56 @@
+.include "macros.inc"
+
+start
+
+test_name ADDI_1
+mvi r1, 0
+addi r3, r1, 0
+check_r3 0
+
+test_name ADDI_2
+mvi r1, 0
+addi r3, r1, 1
+check_r3 1
+
+test_name ADDI_3
+mvi r1, 1
+addi r3, r1, 0
+check_r3 1
+
+test_name ADDI_4
+mvi r1, 1
+addi r3, r1, -1
+check_r3 0
+
+test_name ADDI_5
+mvi r1, -1
+addi r3, r1, 1
+check_r3 0
+
+test_name ADDI_6
+mvi r1, -1
+addi r3, r1, 0
+check_r3 -1
+
+test_name ADDI_7
+mvi r1, 0
+addi r3, r1, -1
+check_r3 -1
+
+test_name ADDI_8
+mvi r3, 4
+addi r3, r3, 4
+check_r3 8
+
+test_name ADDI_9
+mvi r3, 4
+addi r3, r3, -4
+check_r3 0
+
+test_name ADDI_10
+mvi r3, 4
+addi r3, r3, -5
+check_r3 -1
+
+end
+
diff --git a/tests/lm32/test_and.S b/tests/lm32/test_and.S
new file mode 100644
index 0000000..80962ce
--- /dev/null
+++ b/tests/lm32/test_and.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name AND_1
+mvi r1, 0
+mvi r2, 0
+and r3, r1, r2
+check_r3 0
+
+test_name AND_2
+mvi r1, 0
+mvi r2, 1
+and r3, r1, r2
+check_r3 0
+
+test_name AND_3
+mvi r1, 1
+mvi r2, 1
+and r3, r1, r2
+check_r3 1
+
+test_name AND_4
+mvi r3, 7
+and r3, r3, r3
+check_r3 7
+
+test_name AND_5
+mvi r1, 7
+and r3, r1, r1
+check_r3 7
+
+test_name AND_6
+mvi r1, 7
+mvi r3, 0
+and r3, r1, r3
+check_r3 0
+
+test_name AND_7
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+and r3, r1, r2
+check_r3 0
+
+end
diff --git a/tests/lm32/test_andhi.S b/tests/lm32/test_andhi.S
new file mode 100644
index 0000000..4f73af5
--- /dev/null
+++ b/tests/lm32/test_andhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDHI_1
+mvi r1, 0
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_2
+mvi r1, 1
+andhi r3, r1, 1
+check_r3 0
+
+test_name ANDHI_3
+load r1 0x000f0000
+andhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ANDHI_4
+load r1 0xffffffff
+andhi r3, r1, 0xffff
+check_r3 0xffff0000
+
+test_name ANDHI_5
+load r1 0xffffffff
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_6
+load r3 0x55aaffff
+andhi r3, r3, 0xaaaa
+check_r3 0x00aa0000
+
+end
diff --git a/tests/lm32/test_andi.S b/tests/lm32/test_andi.S
new file mode 100644
index 0000000..da1b0a3
--- /dev/null
+++ b/tests/lm32/test_andi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDI_1
+mvi r1, 0
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_2
+mvi r1, 1
+andi r3, r1, 1
+check_r3 1
+
+test_name ANDI_3
+load r1 0x000f0000
+andi r3, r1, 1
+check_r3 0
+
+test_name ANDI_4
+load r1 0xffffffff
+andi r3, r1, 0xffff
+check_r3 0xffff
+
+test_name ANDI_5
+load r1 0xffffffff
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_6
+load r3 0xffff55aa
+andi r3, r3, 0xaaaa
+check_r3 0x000000aa
+
+end
diff --git a/tests/lm32/test_b.S b/tests/lm32/test_b.S
new file mode 100644
index 0000000..98172d8
--- /dev/null
+++ b/tests/lm32/test_b.S
@@ -0,0 +1,13 @@
+.include "macros.inc"
+
+start
+
+test_name B_1
+load r1 jump
+b r1
+tc_fail
+end
+
+jump:
+tc_pass
+end
diff --git a/tests/lm32/test_be.S b/tests/lm32/test_be.S
new file mode 100644
index 0000000..635caba
--- /dev/null
+++ b/tests/lm32/test_be.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BE_1
+mvi r1, 0
+mvi r2, 0
+be r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BE_2
+mvi r1, 1
+mvi r2, 0
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BE_3
+mvi r1, 0
+mvi r2, 1
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BE_4
+mvi r1, 1
+mvi r2, 1
+be r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/lm32/test_bg.S b/tests/lm32/test_bg.S
new file mode 100644
index 0000000..81823c2
--- /dev/null
+++ b/tests/lm32/test_bg.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BG_1
+mvi r1, 0
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_2
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_3
+mvi r1, 0
+mvi r2, 1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_4
+mvi r1, 0
+mvi r2, -1
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_5
+mvi r1, -1
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_6
+mvi r1, -1
+mvi r2, -1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BG_7
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/lm32/test_bge.S b/tests/lm32/test_bge.S
new file mode 100644
index 0000000..6684d15
--- /dev/null
+++ b/tests/lm32/test_bge.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGE_1
+mvi r1, 0
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_2
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_3
+mvi r1, 0
+mvi r2, 1
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_4
+mvi r1, 0
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_5
+mvi r1, -1
+mvi r2, 0
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_6
+mvi r1, -1
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGE_7
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/lm32/test_bgeu.S b/tests/lm32/test_bgeu.S
new file mode 100644
index 0000000..be44030
--- /dev/null
+++ b/tests/lm32/test_bgeu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGEU_1
+mvi r1, 0
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_2
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_3
+mvi r1, 0
+mvi r2, 1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_4
+mvi r1, 0
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_5
+mvi r1, -1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_6
+mvi r1, -1
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGEU_7
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/lm32/test_bgu.S b/tests/lm32/test_bgu.S
new file mode 100644
index 0000000..8cc695b
--- /dev/null
+++ b/tests/lm32/test_bgu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGU_1
+mvi r1, 0
+mvi r2, 0
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_2
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_3
+mvi r1, 0
+mvi r2, 1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_4
+mvi r1, 0
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_5
+mvi r1, -1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_6
+mvi r1, -1
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGU_7
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/lm32/test_bi.S b/tests/lm32/test_bi.S
new file mode 100644
index 0000000..a1fbd6f
--- /dev/null
+++ b/tests/lm32/test_bi.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+start
+
+test_name BI_1
+bi jump
+tc_fail
+end
+
+jump_back:
+tc_pass
+end
+
+jump:
+tc_pass
+
+test_name BI_2
+bi jump_back
+tc_fail
+
+end
+
+
diff --git a/tests/lm32/test_bne.S b/tests/lm32/test_bne.S
new file mode 100644
index 0000000..871a006
--- /dev/null
+++ b/tests/lm32/test_bne.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BNE_1
+mvi r1, 0
+mvi r2, 0
+bne r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BNE_2
+mvi r1, 1
+mvi r2, 0
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BNE_3
+mvi r1, 0
+mvi r2, 1
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_fail
+bi 3f
+2:
+test_name BNE_4
+mvi r1, 1
+mvi r2, 1
+bne r1, r2, 1b
+tc_pass
+3:
+
+end
+
diff --git a/tests/lm32/test_break.S b/tests/lm32/test_break.S
new file mode 100644
index 0000000..0384fc6
--- /dev/null
+++ b/tests/lm32/test_break.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name BREAK_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+break
+check_excp 1
+
+test_name BREAK_2
+mv r3, ba
+check_r3 insn
+
+test_name BREAK_3
+rcsr r3, IE
+check_r3 4
+
+end
diff --git a/tests/lm32/test_bret.S b/tests/lm32/test_bret.S
new file mode 100644
index 0000000..645210e
--- /dev/null
+++ b/tests/lm32/test_bret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name BRET_1
+mvi r1, 4
+wcsr IE, r1
+load ba mark
+bret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name BRET_2
+rcsr r3, IE
+check_r3 5
+
+test_name BRET_3
+mvi r1, 0
+wcsr IE, r1
+load ba mark2
+bret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name BRET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/lm32/test_call.S b/tests/lm32/test_call.S
new file mode 100644
index 0000000..1b91a5f
--- /dev/null
+++ b/tests/lm32/test_call.S
@@ -0,0 +1,16 @@
+.include "macros.inc"
+
+start
+
+test_name CALL_1
+load r1 mark
+call r1
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/lm32/test_calli.S b/tests/lm32/test_calli.S
new file mode 100644
index 0000000..1d87ae6
--- /dev/null
+++ b/tests/lm32/test_calli.S
@@ -0,0 +1,15 @@
+.include "macros.inc"
+
+start
+
+test_name CALLI_1
+calli mark
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/lm32/test_cmpe.S b/tests/lm32/test_cmpe.S
new file mode 100644
index 0000000..60a8855
--- /dev/null
+++ b/tests/lm32/test_cmpe.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPE_1
+mvi r1, 0
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 1
+
+test_name CMPE_2
+mvi r1, 0
+mvi r2, 1
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_3
+mvi r1, 1
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_4
+mvi r3, 0
+mvi r2, 1
+cmpe r3, r3, r2
+check_r3 0
+
+test_name CMPE_5
+mvi r3, 0
+mvi r2, 0
+cmpe r3, r3, r2
+check_r3 1
+
+test_name CMPE_6
+mvi r3, 0
+cmpe r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/lm32/test_cmpei.S b/tests/lm32/test_cmpei.S
new file mode 100644
index 0000000..c3d3566
--- /dev/null
+++ b/tests/lm32/test_cmpei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPEI_1
+mvi r1, 0
+cmpei r3, r1, 0
+check_r3 1
+
+test_name CMPEI_2
+mvi r1, 0
+cmpei r3, r1, 1
+check_r3 0
+
+test_name CMPEI_3
+mvi r1, 1
+cmpei r3, r1, 0
+check_r3 0
+
+test_name CMPEI_4
+load r1 0xffffffff
+cmpei r3, r1, -1
+check_r3 1
+
+test_name CMPEI_5
+mvi r3, 0
+cmpei r3, r3, 0
+check_r3 1
+
+test_name CMPEI_6
+mvi r3, 0
+cmpei r3, r3, 1
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpg.S b/tests/lm32/test_cmpg.S
new file mode 100644
index 0000000..0124078
--- /dev/null
+++ b/tests/lm32/test_cmpg.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPG_1
+mvi r1, 0
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_2
+mvi r1, 0
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_3
+mvi r1, 1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_4
+mvi r1, 1
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_5
+mvi r1, 0
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_6
+mvi r1, -1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_7
+mvi r1, -1
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_8
+mvi r3, 0
+mvi r2, 1
+cmpg r3, r3, r2
+check_r3 0
+
+test_name CMPG_9
+mvi r3, 1
+mvi r2, 0
+cmpg r3, r3, r2
+check_r3 1
+
+test_name CMPG_10
+mvi r3, 0
+cmpg r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpge.S b/tests/lm32/test_cmpge.S
new file mode 100644
index 0000000..84620a0
--- /dev/null
+++ b/tests/lm32/test_cmpge.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGE_1
+mvi r1, 0
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_2
+mvi r1, 0
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_3
+mvi r1, 1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_4
+mvi r1, 1
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_5
+mvi r1, 0
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_6
+mvi r1, -1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_7
+mvi r1, -1
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_8
+mvi r3, 0
+mvi r2, 1
+cmpge r3, r3, r2
+check_r3 0
+
+test_name CMPGE_9
+mvi r3, 1
+mvi r2, 0
+cmpge r3, r3, r2
+check_r3 1
+
+test_name CMPGE_10
+mvi r3, 0
+cmpge r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/lm32/test_cmpgei.S b/tests/lm32/test_cmpgei.S
new file mode 100644
index 0000000..6a8870f
--- /dev/null
+++ b/tests/lm32/test_cmpgei.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEI_1
+mvi r1, 0
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_2
+mvi r1, 0
+cmpgei r3, r1, 1
+check_r3 0
+
+test_name CMPGEI_3
+mvi r1, 1
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_4
+mvi r1, 1
+cmpgei r3, r1, 1
+check_r3 1
+
+test_name CMPGEI_5
+mvi r1, 0
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_6
+mvi r1, -1
+cmpgei r3, r1, 0
+check_r3 0
+
+test_name CMPGEI_7
+mvi r1, -1
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_8
+mvi r3, 0
+cmpgei r3, r3, 1
+check_r3 0
+
+test_name CMPGEI_9
+mvi r3, 1
+cmpgei r3, r3, 0
+check_r3 1
+
+test_name CMPGEI_10
+mvi r3, 0
+cmpgei r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/lm32/test_cmpgeu.S b/tests/lm32/test_cmpgeu.S
new file mode 100644
index 0000000..2110ccb
--- /dev/null
+++ b/tests/lm32/test_cmpgeu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEU_1
+mvi r1, 0
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_2
+mvi r1, 0
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_3
+mvi r1, 1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_4
+mvi r1, 1
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_5
+mvi r1, 0
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_6
+mvi r1, -1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_7
+mvi r1, -1
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_8
+mvi r3, 0
+mvi r2, 1
+cmpgeu r3, r3, r2
+check_r3 0
+
+test_name CMPGEU_9
+mvi r3, 1
+mvi r2, 0
+cmpgeu r3, r3, r2
+check_r3 1
+
+test_name CMPGEU_10
+mvi r3, 0
+cmpgeu r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/lm32/test_cmpgeui.S b/tests/lm32/test_cmpgeui.S
new file mode 100644
index 0000000..b9d1755
--- /dev/null
+++ b/tests/lm32/test_cmpgeui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEUI_1
+mvi r1, 0
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_2
+mvi r1, 0
+cmpgeui r3, r1, 1
+check_r3 0
+
+test_name CMPGEUI_3
+mvi r1, 1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_4
+mvi r1, 1
+cmpgeui r3, r1, 1
+check_r3 1
+
+test_name CMPGEUI_5
+mvi r1, 0
+cmpgeui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGEUI_6
+mvi r1, -1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_7
+mvi r1, -1
+cmpgeui r3, r1, 0xffff
+check_r3 1
+
+test_name CMPGEUI_8
+mvi r3, 0
+cmpgeui r3, r3, 1
+check_r3 0
+
+test_name CMPGEUI_9
+mvi r3, 1
+cmpgeui r3, r3, 0
+check_r3 1
+
+test_name CMPGEUI_10
+mvi r3, 0
+cmpgeui r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/lm32/test_cmpgi.S b/tests/lm32/test_cmpgi.S
new file mode 100644
index 0000000..1f622d2
--- /dev/null
+++ b/tests/lm32/test_cmpgi.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGI_1
+mvi r1, 0
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_2
+mvi r1, 0
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_3
+mvi r1, 1
+cmpgi r3, r1, 0
+check_r3 1
+
+test_name CMPGI_4
+mvi r1, 1
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_5
+mvi r1, 0
+cmpgi r3, r1, -1
+check_r3 1
+
+test_name CMPGI_6
+mvi r1, -1
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_7
+mvi r1, -1
+cmpgi r3, r1, -1
+check_r3 0
+
+test_name CMPGI_8
+mvi r3, 0
+cmpgi r3, r3, 1
+check_r3 0
+
+test_name CMPGI_9
+mvi r3, 1
+cmpgi r3, r3, 0
+check_r3 1
+
+test_name CMPGI_10
+mvi r3, 0
+cmpgi r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpgu.S b/tests/lm32/test_cmpgu.S
new file mode 100644
index 0000000..dd46547
--- /dev/null
+++ b/tests/lm32/test_cmpgu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGU_1
+mvi r1, 0
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_2
+mvi r1, 0
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_3
+mvi r1, 1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_4
+mvi r1, 1
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_5
+mvi r1, 0
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_6
+mvi r1, -1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_7
+mvi r1, -1
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_8
+mvi r3, 0
+mvi r2, 1
+cmpgu r3, r3, r2
+check_r3 0
+
+test_name CMPGU_9
+mvi r3, 1
+mvi r2, 0
+cmpgu r3, r3, r2
+check_r3 1
+
+test_name CMPGU_10
+mvi r3, 0
+cmpgu r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpgui.S b/tests/lm32/test_cmpgui.S
new file mode 100644
index 0000000..759bb64
--- /dev/null
+++ b/tests/lm32/test_cmpgui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGUI_1
+mvi r1, 0
+cmpgui r3, r1, 0
+check_r3 0
+
+test_name CMPGUI_2
+mvi r1, 0
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_3
+mvi r1, 1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_4
+mvi r1, 1
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_5
+mvi r1, 0
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_6
+mvi r1, -1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_7
+mvi r1, -1
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_8
+mvi r3, 0
+cmpgui r3, r3, 1
+check_r3 0
+
+test_name CMPGUI_9
+mvi r3, 1
+cmpgui r3, r3, 0
+check_r3 1
+
+test_name CMPGUI_10
+mvi r3, 0
+cmpgui r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpne.S b/tests/lm32/test_cmpne.S
new file mode 100644
index 0000000..0f10781
--- /dev/null
+++ b/tests/lm32/test_cmpne.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNE_1
+mvi r1, 0
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 0
+
+test_name CMPNE_2
+mvi r1, 0
+mvi r2, 1
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_3
+mvi r1, 1
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_4
+mvi r3, 0
+mvi r2, 1
+cmpne r3, r3, r2
+check_r3 1
+
+test_name CMPNE_5
+mvi r3, 0
+mvi r2, 0
+cmpne r3, r3, r2
+check_r3 0
+
+test_name CMPNE_6
+mvi r3, 0
+cmpne r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/lm32/test_cmpnei.S b/tests/lm32/test_cmpnei.S
new file mode 100644
index 0000000..060dd9d
--- /dev/null
+++ b/tests/lm32/test_cmpnei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNEI_1
+mvi r1, 0
+cmpnei r3, r1, 0
+check_r3 0
+
+test_name CMPNEI_2
+mvi r1, 0
+cmpnei r3, r1, 1
+check_r3 1
+
+test_name CMPNEI_3
+mvi r1, 1
+cmpnei r3, r1, 0
+check_r3 1
+
+test_name CMPNEI_4
+load r1 0xffffffff
+cmpnei r3, r1, -1
+check_r3 0
+
+test_name CMPNEI_5
+mvi r3, 0
+cmpnei r3, r3, 0
+check_r3 0
+
+test_name CMPNEI_6
+mvi r3, 0
+cmpnei r3, r3, 1
+check_r3 1
+
+end
diff --git a/tests/lm32/test_divu.S b/tests/lm32/test_divu.S
new file mode 100644
index 0000000..f381d09
--- /dev/null
+++ b/tests/lm32/test_divu.S
@@ -0,0 +1,29 @@
+.include "macros.inc"
+
+start
+
+test_name DIVU_1
+mvi r1, 0
+mvi r2, 1
+divu r3, r1, r2
+check_r3 0
+
+test_name DIVU_2
+mvi r1, 1
+mvi r2, 1
+divu r3, r1, r2
+check_r3 1
+
+test_name DIVU_3
+mvi r1, 0
+mvi r2, 0
+divu r3, r1, r2
+check_excp 16
+
+test_name DIVU_4
+load r1 0xabcdef12
+load r2 0x12345
+divu r3, r1, r2
+check_r3 0x9700
+
+end
diff --git a/tests/lm32/test_eret.S b/tests/lm32/test_eret.S
new file mode 100644
index 0000000..6830bd1
--- /dev/null
+++ b/tests/lm32/test_eret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name ERET_1
+mvi r1, 2
+wcsr IE, r1
+load ea mark
+eret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name ERET_2
+rcsr r3, IE
+check_r3 3
+
+test_name ERET_3
+mvi r1, 0
+wcsr IE, r1
+load ea mark2
+eret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name ERET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/lm32/test_lb.S b/tests/lm32/test_lb.S
new file mode 100644
index 0000000..f84d21e
--- /dev/null
+++ b/tests/lm32/test_lb.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LB_1
+load r1 data
+lb r3, (r1+0)
+check_r3 0x7e
+
+test_name LB_2
+lb r3, (r1+1)
+check_r3 0x7f
+
+test_name LB_3
+lb r3, (r1+-1)
+check_r3 0x7d
+
+test_name LB_4
+load r1 data_msb
+lb r3, (r1+0)
+check_r3 0xfffffffe
+
+test_name LB_5
+lb r3, (r1+1)
+check_r3 0xffffffff
+
+test_name LB_6
+lb r3, (r1+-1)
+check_r3 0xfffffffd
+
+test_name LB_7
+load r3 data
+lb r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lbu.S b/tests/lm32/test_lbu.S
new file mode 100644
index 0000000..4c1786a
--- /dev/null
+++ b/tests/lm32/test_lbu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LBU_1
+load r1 data
+lbu r3, (r1+0)
+check_r3 0x7e
+
+test_name LBU_2
+lbu r3, (r1+1)
+check_r3 0x7f
+
+test_name LBU_3
+lbu r3, (r1+-1)
+check_r3 0x7d
+
+test_name LBU_4
+load r1 data_msb
+lbu r3, (r1+0)
+check_r3 0xfe
+
+test_name LBU_5
+lbu r3, (r1+1)
+check_r3 0xff
+
+test_name LBU_6
+lbu r3, (r1+-1)
+check_r3 0xfd
+
+test_name LBU_7
+load r3 data
+lbu r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lh.S b/tests/lm32/test_lh.S
new file mode 100644
index 0000000..e57d9e3
--- /dev/null
+++ b/tests/lm32/test_lh.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LH_1
+load r1 data
+lh r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LH_2
+lh r3, (r1+2)
+check_r3 0x7071
+
+test_name LH_3
+lh r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LH_4
+load r1 data_msb
+lh r3, (r1+0)
+check_r3 0xfffffeff
+
+test_name LH_5
+lh r3, (r1+2)
+check_r3 0xfffff0f1
+
+test_name LH_6
+lh r3, (r1+-2)
+check_r3 0xfffffcfd
+
+test_name LH_7
+load r3 data
+lh r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lhu.S b/tests/lm32/test_lhu.S
new file mode 100644
index 0000000..e648775
--- /dev/null
+++ b/tests/lm32/test_lhu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LHU_1
+load r1 data
+lhu r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LHU_2
+lhu r3, (r1+2)
+check_r3 0x7071
+
+test_name LHU_3
+lhu r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LHU_4
+load r1 data_msb
+lhu r3, (r1+0)
+check_r3 0xfeff
+
+test_name LHU_5
+lhu r3, (r1+2)
+check_r3 0xf0f1
+
+test_name LHU_6
+lhu r3, (r1+-2)
+check_r3 0xfcfd
+
+test_name LHU_7
+load r3 data
+lhu r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+	.byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/lm32/test_lw.S b/tests/lm32/test_lw.S
new file mode 100644
index 0000000..f8c919d
--- /dev/null
+++ b/tests/lm32/test_lw.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name LW_1
+load r1 data
+lw r3, (r1+0)
+check_r3 0x7e7f7071
+
+test_name LW_2
+lw r3, (r1+4)
+check_r3 0x72737475
+
+test_name LW_3
+lw r3, (r1+-4)
+check_r3 0x7a7b7c7d
+
+test_name LW_4
+load r3 data
+lw r3, (r3+0)
+check_r3 0x7e7f7071
+
+end
+
+.data
+	.align 4
+	.byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+	.byte 0x7e, 0x7f, 0x70, 0x71
+	.byte 0x72, 0x73, 0x74, 0x75
diff --git a/tests/lm32/test_modu.S b/tests/lm32/test_modu.S
new file mode 100644
index 0000000..4248690
--- /dev/null
+++ b/tests/lm32/test_modu.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name MODU_1
+mvi r1, 0
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_2
+mvi r1, 1
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_3
+mvi r1, 3
+mvi r2, 2
+modu r3, r1, r2
+check_r3 1
+
+test_name MODU_4
+mvi r1, 0
+mvi r2, 0
+modu r3, r1, r2
+check_excp 16
+
+test_name MODU_5
+load r1 0xabcdef12
+load r2 0x12345
+modu r3, r1, r2
+check_r3 0x3c12
+
+end
diff --git a/tests/lm32/test_mul.S b/tests/lm32/test_mul.S
new file mode 100644
index 0000000..e9b937e
--- /dev/null
+++ b/tests/lm32/test_mul.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name MUL_1
+mvi r1, 0
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_2
+mvi r1, 1
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_3
+mvi r1, 0
+mvi r2, 1
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_4
+mvi r1, 1
+mvi r2, 1
+mul r3, r1, r2
+check_r3 1
+
+test_name MUL_5
+mvi r1, 2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 -2
+
+test_name MUL_6
+mvi r1, -2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 2
+
+test_name MUL_7
+mvi r1, 0x1234
+mvi r2, 0x789
+mul r3, r1, r2
+check_r3 0x8929d4
+
+test_name MUL_8
+mvi r3, 4
+mul r3, r3, r3
+check_r3 16
+
+test_name MUL_9
+mvi r2, 2
+mvi r3, 4
+mul r3, r3, r2
+check_r3 8
+
+test_name MUL_10
+load r1 0x12345678
+load r2 0x7bcdef12
+mul r3, r1, r2
+check_r3 0xa801c70
+
+test_name MUL_11
+load r1 0x12345678
+load r2 0xabcdef12
+mul r3, r1, r2
+check_r3 0x8a801c70
+
+end
diff --git a/tests/lm32/test_muli.S b/tests/lm32/test_muli.S
new file mode 100644
index 0000000..d6dd4a0
--- /dev/null
+++ b/tests/lm32/test_muli.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name MULI_1
+mvi r1, 0
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_2
+mvi r1, 1
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_3
+mvi r1, 0
+muli r3, r1, 1
+check_r3 0
+
+test_name MULI_4
+mvi r1, 1
+muli r3, r1, 1
+check_r3 1
+
+test_name MULI_5
+mvi r1, 2
+muli r3, r1, -1
+check_r3 -2
+
+test_name MULI_6
+mvi r1, -2
+muli r3, r1, -1
+check_r3 2
+
+test_name MULI_7
+mvi r1, 0x1234
+muli r3, r1, 0x789
+check_r3 0x8929d4
+
+test_name MULI_8
+mvi r3, 4
+muli r3, r3, 4
+check_r3 16
+
+end
diff --git a/tests/lm32/test_nor.S b/tests/lm32/test_nor.S
new file mode 100644
index 0000000..74d7592
--- /dev/null
+++ b/tests/lm32/test_nor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name NOR_1
+mvi r1, 0
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xffffffff
+
+test_name NOR_2
+mvi r1, 0
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_3
+mvi r1, 1
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_4
+mvi r1, 1
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+nor r3, r1, r2
+check_r3 0
+
+test_name NOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+nor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name NOR_7
+load r1 0xaa55aa55
+nor r3, r1, r1
+check_r3 0x55aa55aa
+
+test_name NOR_8
+load r3 0xaa55aa55
+nor r3, r3, r3
+check_r3 0x55aa55aa
+
+end
diff --git a/tests/lm32/test_nori.S b/tests/lm32/test_nori.S
new file mode 100644
index 0000000..d00309c
--- /dev/null
+++ b/tests/lm32/test_nori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name NORI_1
+mvi r1, 0
+nori r3, r1, 0
+check_r3 0xffffffff
+
+test_name NORI_2
+mvi r1, 0
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_3
+mvi r1, 1
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_4
+mvi r1, 1
+nori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name NORI_5
+load r1 0xaa55aa55
+nori r3, r1, 0x55aa
+check_r3 0x55aa0000
+
+test_name NORI_6
+load r3 0xaa55aa55
+nori r3, r3, 0x55aa
+check_r3 0x55aa0000
+
+end
diff --git a/tests/lm32/test_or.S b/tests/lm32/test_or.S
new file mode 100644
index 0000000..4ed2923
--- /dev/null
+++ b/tests/lm32/test_or.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name OR_1
+mvi r1, 0
+mvi r2, 0
+or r3, r1, r2
+check_r3 0
+
+test_name OR_2
+mvi r1, 0
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_3
+mvi r1, 1
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_4
+mvi r1, 1
+mvi r2, 0
+or r3, r1, r2
+check_r3 1
+
+test_name OR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+or r3, r1, r2
+check_r3 0xffffffff
+
+test_name OR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+or r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name OR_7
+load r1 0xaa55aa55
+or r3, r1, r1
+check_r3 0xaa55aa55
+
+test_name OR_8
+load r3 0xaa55aa55
+or r3, r3, r3
+check_r3 0xaa55aa55
+
+end
diff --git a/tests/lm32/test_orhi.S b/tests/lm32/test_orhi.S
new file mode 100644
index 0000000..78b7600
--- /dev/null
+++ b/tests/lm32/test_orhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORHI_1
+mvi r1, 0
+orhi r3, r1, 0
+check_r3 0
+
+test_name ORHI_2
+mvi r1, 0
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_3
+load r1 0x00010000
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_4
+mvi r1, 1
+orhi r3, r1, 0
+check_r3 1
+
+test_name ORHI_5
+load r1 0xaa55aa55
+orhi r3, r1, 0x55aa
+check_r3 0xffffaa55
+
+test_name ORHI_6
+load r3 0xaa55aa55
+orhi r3, r3, 0x55aa
+check_r3 0xffffaa55
+
+end
diff --git a/tests/lm32/test_ori.S b/tests/lm32/test_ori.S
new file mode 100644
index 0000000..3d576cd
--- /dev/null
+++ b/tests/lm32/test_ori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORI_1
+mvi r1, 0
+ori r3, r1, 0
+check_r3 0
+
+test_name ORI_2
+mvi r1, 0
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_3
+mvi r1, 1
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_4
+mvi r1, 1
+ori r3, r1, 0
+check_r3 1
+
+test_name ORI_5
+load r1 0xaa55aa55
+ori r3, r1, 0x55aa
+check_r3 0xaa55ffff
+
+test_name ORI_6
+load r3 0xaa55aa55
+ori r3, r3, 0x55aa
+check_r3 0xaa55ffff
+
+end
diff --git a/tests/lm32/test_ret.S b/tests/lm32/test_ret.S
new file mode 100644
index 0000000..320264f
--- /dev/null
+++ b/tests/lm32/test_ret.S
@@ -0,0 +1,14 @@
+.include "macros.inc"
+
+start
+
+test_name RET_1
+load ra mark
+ret
+
+tc_fail
+end
+
+mark:
+tc_pass
+end
diff --git a/tests/lm32/test_sb.S b/tests/lm32/test_sb.S
new file mode 100644
index 0000000..89e39d6
--- /dev/null
+++ b/tests/lm32/test_sb.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SB_1
+load r1 data
+load r2 0xf0f1f2aa
+sb (r1+0), r2
+check_mem data 0xaa000000
+
+test_name SB_2
+load r2 0xf0f1f2bb
+sb (r1+1), r2
+check_mem data 0xaabb0000
+
+test_name SB_3
+load r2 0xf0f1f2cc
+sb (r1+-1), r2
+check_mem data0 0x000000cc
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_scall.S b/tests/lm32/test_scall.S
new file mode 100644
index 0000000..b442e32
--- /dev/null
+++ b/tests/lm32/test_scall.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SCALL_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+scall
+check_excp 64
+
+test_name SCALL_2
+mv r3, ea
+check_r3 insn
+
+test_name SCALL_3
+rcsr r3, IE
+check_r3 2
+
+end
diff --git a/tests/lm32/test_sextb.S b/tests/lm32/test_sextb.S
new file mode 100644
index 0000000..58db8ee
--- /dev/null
+++ b/tests/lm32/test_sextb.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTB_1
+mvi r1, 0
+sextb r3, r1
+check_r3 0
+
+test_name SEXTB_2
+mvi r1, 0x7f
+sextb r3, r1
+check_r3 0x0000007f
+
+test_name SEXTB_3
+mvi r1, 0x80
+sextb r3, r1
+check_r3 0xffffff80
+
+end
diff --git a/tests/lm32/test_sexth.S b/tests/lm32/test_sexth.S
new file mode 100644
index 0000000..a059ec3
--- /dev/null
+++ b/tests/lm32/test_sexth.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTH_1
+mvi r1, 0
+sexth r3, r1
+check_r3 0
+
+test_name SEXTH_2
+load r1 0x7fff
+sexth r3, r1
+check_r3 0x00007fff
+
+test_name SEXTH_3
+load r1 0x8000
+sexth r3, r1
+check_r3 0xffff8000
+
+end
diff --git a/tests/lm32/test_sh.S b/tests/lm32/test_sh.S
new file mode 100644
index 0000000..ea8b3f2
--- /dev/null
+++ b/tests/lm32/test_sh.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SH_1
+load r1 data
+load r2 0xf0f1aaaa
+sh (r1+0), r2
+check_mem data 0xaaaa0000
+
+test_name SH_2
+load r2 0xf0f1bbbb
+sh (r1+2), r2
+check_mem data 0xaaaabbbb
+
+test_name SH_3
+load r2 0xf0f1cccc
+sh (r1+-2), r2
+check_mem data0 0x0000cccc
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_sl.S b/tests/lm32/test_sl.S
new file mode 100644
index 0000000..0aee17f
--- /dev/null
+++ b/tests/lm32/test_sl.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name SL_1
+mvi r1, 1
+mvi r2, 0
+sl r3, r1, r2
+check_r3 1
+
+test_name SL_2
+mvi r1, 0
+mvi r2, 1
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_3
+mvi r1, 1
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0x80000000
+
+test_name SL_4
+mvi r1, 16
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_5
+mvi r1, 1
+mvi r2, 34
+sl r3, r1, r2
+check_r3 4
+
+test_name SL_6
+mvi r1, 2
+sl r3, r1, r1
+check_r3 8
+
+test_name SL_7
+mvi r3, 2
+sl r3, r3, r3
+check_r3 8
+
+end
diff --git a/tests/lm32/test_sli.S b/tests/lm32/test_sli.S
new file mode 100644
index 0000000..a421de9
--- /dev/null
+++ b/tests/lm32/test_sli.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SLI_1
+mvi r1, 1
+sli r3, r1, 0
+check_r3 1
+
+test_name SLI_2
+mvi r1, 0
+sli r3, r1, 1
+check_r3 0
+
+test_name SLI_3
+mvi r1, 1
+sli r3, r1, 31
+check_r3 0x80000000
+
+test_name SLI_4
+mvi r1, 16
+sli r3, r1, 31
+check_r3 0
+
+test_name SLI_7
+mvi r3, 2
+sli r3, r3, 2
+check_r3 8
+
+end
diff --git a/tests/lm32/test_sr.S b/tests/lm32/test_sr.S
new file mode 100644
index 0000000..62431a9
--- /dev/null
+++ b/tests/lm32/test_sr.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SR_1
+mvi r1, 1
+mvi r2, 0
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_2
+mvi r1, 0
+mvi r2, 1
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_3
+load r1 0x40000000
+mvi r2, 30
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_4
+load r1 0x40000000
+mvi r2, 31
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_5
+mvi r1, 16
+mvi r2, 34
+sr r3, r1, r2
+check_r3 4
+
+test_name SR_6
+mvi r1, 2
+sr r3, r1, r1
+check_r3 0
+
+test_name SR_7
+mvi r3, 2
+sr r3, r3, r3
+check_r3 0
+
+test_name SR_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sr r3, r1, r2
+check_r3 0xfffffffc
+
+test_name SR_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sr r3, r1, r2
+check_r3 0xffffffff
+
+end
diff --git a/tests/lm32/test_sri.S b/tests/lm32/test_sri.S
new file mode 100644
index 0000000..c1be907
--- /dev/null
+++ b/tests/lm32/test_sri.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRI_1
+mvi r1, 1
+sri r3, r1, 0
+check_r3 1
+
+test_name SRI_2
+mvi r1, 0
+sri r3, r1, 1
+check_r3 0
+
+test_name SRI_3
+load r1 0x40000000
+sri r3, r1, 30
+check_r3 1
+
+test_name SRI_4
+load r1 0x40000000
+sri r3, r1, 31
+check_r3 0
+
+test_name SRI_5
+mvi r3, 2
+sri r3, r3, 2
+check_r3 0
+
+test_name SRI_6
+mvi r1, 0xfffffff0
+sri r3, r1, 2
+check_r3 0xfffffffc
+
+test_name SRI_7
+mvi r1, 0xfffffff0
+sri r3, r1, 4
+check_r3 0xffffffff
+
+end
diff --git a/tests/lm32/test_sru.S b/tests/lm32/test_sru.S
new file mode 100644
index 0000000..2ab0b54
--- /dev/null
+++ b/tests/lm32/test_sru.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SRU_1
+mvi r1, 1
+mvi r2, 0
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_2
+mvi r1, 0
+mvi r2, 1
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_3
+load r1 0x40000000
+mvi r2, 30
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_4
+load r1 0x40000000
+mvi r2, 31
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_5
+mvi r1, 16
+mvi r2, 34
+sru r3, r1, r2
+check_r3 4
+
+test_name SRU_6
+mvi r1, 2
+sru r3, r1, r1
+check_r3 0
+
+test_name SRU_7
+mvi r3, 2
+sru r3, r3, r3
+check_r3 0
+
+test_name SRU_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sru r3, r1, r2
+check_r3 0x3ffffffc
+
+test_name SRU_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sru r3, r1, r2
+check_r3 0x0fffffff
+
+end
diff --git a/tests/lm32/test_srui.S b/tests/lm32/test_srui.S
new file mode 100644
index 0000000..872c374
--- /dev/null
+++ b/tests/lm32/test_srui.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRUI_1
+mvi r1, 1
+srui r3, r1, 0
+check_r3 1
+
+test_name SRUI_2
+mvi r1, 0
+srui r3, r1, 1
+check_r3 0
+
+test_name SRUI_3
+load r1 0x40000000
+srui r3, r1, 30
+check_r3 1
+
+test_name SRUI_4
+load r1 0x40000000
+srui r3, r1, 31
+check_r3 0
+
+test_name SRUI_5
+mvi r3, 2
+srui r3, r3, 2
+check_r3 0
+
+test_name SRUI_6
+mvi r1, 0xfffffff0
+srui r3, r1, 2
+check_r3 0x3ffffffc
+
+test_name SRUI_7
+mvi r1, 0xfffffff0
+srui r3, r1, 4
+check_r3 0x0fffffff
+
+end
diff --git a/tests/lm32/test_sub.S b/tests/lm32/test_sub.S
new file mode 100644
index 0000000..44b74a9
--- /dev/null
+++ b/tests/lm32/test_sub.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name SUB_1
+mvi r1, 0
+mvi r2, 0
+sub r3, r1, r2
+check_r3 0
+
+test_name SUB_2
+mvi r1, 0
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_3
+mvi r1, 1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_4
+mvi r1, 1
+mvi r2, -1
+sub r3, r1, r2
+check_r3 2
+
+test_name SUB_5
+mvi r1, -1
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -2
+
+test_name SUB_6
+mvi r1, -1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_7
+mvi r1, 0
+mvi r2, -1
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_8
+mvi r3, 2
+sub r3, r3, r3
+check_r3 0
+
+test_name SUB_9
+mvi r1, 4
+mvi r3, 2
+sub r3, r1, r3
+check_r3 2
+
+test_name SUB_10
+mvi r1, 4
+mvi r3, 2
+sub r3, r3, r1
+check_r3 -2
+
+test_name SUB_11
+mvi r1, 4
+sub r3, r1, r1
+check_r3 0
+
+test_name SUB_12
+load r1 0x12345678
+load r2 0xabcdef97
+sub r3, r1, r2
+check_r3 0x666666e1
+
+end
diff --git a/tests/lm32/test_sw.S b/tests/lm32/test_sw.S
new file mode 100644
index 0000000..d1fdadc
--- /dev/null
+++ b/tests/lm32/test_sw.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name SW_1
+load r1 data
+load r2 0xaabbccdd
+sw (r1+0), r2
+check_mem data 0xaabbccdd
+
+test_name SW_2
+load r2 0x00112233
+sw (r1+4), r2
+check_mem data1 0x00112233
+
+test_name SW_3
+load r2 0x44556677
+sw (r1+-4), r2
+check_mem data0 0x44556677
+
+test_name SW_4
+sw (r1+0), r1
+lw r3, (r1+0)
+check_r3 data
+
+end
+
+.data
+	.align 4
+data0:
+	.byte 0, 0, 0, 0
+data:
+	.byte 0, 0, 0, 0
+data1:
+	.byte 0, 0, 0, 0
diff --git a/tests/lm32/test_xnor.S b/tests/lm32/test_xnor.S
new file mode 100644
index 0000000..14a6207
--- /dev/null
+++ b/tests/lm32/test_xnor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XNOR_1
+mvi r1, 0
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_2
+mvi r1, 0
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_3
+mvi r1, 1
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_4
+mvi r1, 1
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xnor r3, r1, r2
+check_r3 0
+
+test_name XNOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xnor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name XNOR_7
+load r1 0xaa55aa55
+xnor r3, r1, r1
+check_r3 0xffffffff
+
+test_name XNOR_8
+load r3 0xaa55aa55
+xnor r3, r3, r3
+check_r3 0xffffffff
+
+end
diff --git a/tests/lm32/test_xnori.S b/tests/lm32/test_xnori.S
new file mode 100644
index 0000000..9d9c3c6
--- /dev/null
+++ b/tests/lm32/test_xnori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XNORI_1
+mvi r1, 0
+xnori r3, r1, 0
+check_r3 0xffffffff
+
+test_name XNORI_2
+mvi r1, 0
+xnori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name XNORI_3
+mvi r1, 1
+xnori r3, r1, 1
+check_r3 0xffffffff
+
+test_name XNORI_4
+mvi r1, 1
+xnori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name XNORI_5
+load r1 0xaa55aa55
+xnori r3, r1, 0x5555
+check_r3 0x55aa00ff
+
+test_name XNORI_6
+load r3 0xaa55aa55
+xnori r3, r3, 0x5555
+check_r3 0x55aa00ff
+
+end
diff --git a/tests/lm32/test_xor.S b/tests/lm32/test_xor.S
new file mode 100644
index 0000000..6c6e712
--- /dev/null
+++ b/tests/lm32/test_xor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XOR_1
+mvi r1, 0
+mvi r2, 0
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_2
+mvi r1, 0
+mvi r2, 1
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_3
+mvi r1, 1
+mvi r2, 1
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_4
+mvi r1, 1
+mvi r2, 0
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xor r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name XOR_7
+load r1 0xaa55aa55
+xor r3, r1, r1
+check_r3 0
+
+test_name XOR_8
+load r3 0xaa55aa55
+xor r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/lm32/test_xori.S b/tests/lm32/test_xori.S
new file mode 100644
index 0000000..2051699
--- /dev/null
+++ b/tests/lm32/test_xori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XORI_1
+mvi r1, 0
+xori r3, r1, 0
+check_r3 0
+
+test_name XORI_2
+mvi r1, 0
+xori r3, r1, 1
+check_r3 1
+
+test_name XORI_3
+mvi r1, 1
+xori r3, r1, 1
+check_r3 0
+
+test_name XORI_4
+mvi r1, 1
+xori r3, r1, 0
+check_r3 1
+
+test_name XORI_5
+load r1 0xaa55aa55
+xori r3, r1, 0x5555
+check_r3 0xaa55ff00
+
+test_name XORI_6
+load r3 0xaa55aa55
+xori r3, r3, 0x5555
+check_r3 0xaa55ff00
+
+end
commit 45664345fa3d6f2833177533c959f34867bbe573
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:15 2011 +0100

    lm32: todo and documentation
    
    This patch adds general target documentation and a todo list.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/README b/target-lm32/README
new file mode 100644
index 0000000..a1c2c7e
--- /dev/null
+++ b/target-lm32/README
@@ -0,0 +1,46 @@
+LatticeMico32 target
+--------------------
+
+General
+-------
+All opcodes including the JUART CSRs are supported.
+
+
+JTAG UART
+---------
+JTAG UART is routed to a serial console device. For the current boards it
+is the second one. Ie to enable it in the qemu virtual console window use
+the following command line parameters:
+  -serial vc -serial vc
+This will make serial0 (the lm32_uart) and serial1 (the JTAG UART)
+available as virtual consoles.
+
+
+Programmatically terminate the emulator
+----------------------------------------
+Originally neither the LatticeMico32 nor its peripherals support a
+mechanism to shut down the machine. Emulation aware programs can write to a
+to a special register within the system control block to shut down the
+virtual machine.  For more details see hw/lm32_sys.c. The lm32-evr is the
+first BSP which instantiate this model. A (32 bit) write to 0xfff0000
+causes a vm shutdown.
+
+
+Special instructions
+--------------------
+The translation recognizes one special instruction to halt the cpu:
+  and r0, r0, r0
+On real hardware this instruction is a nop. It is not used by GCC and
+should (hopefully) not be used within hand-crafted assembly.
+Insert this instruction in your idle loop to reduce the cpu load on the
+host.
+
+
+Ignoring the MSB of the address bus
+-----------------------------------
+Some SoC ignores the MSB on the address bus. Thus creating a shadow memory
+area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
+0x80000000-0xffffffff is not cached and used to access IO devices. This
+behaviour can be enabled with:
+  cpu_lm32_set_phys_msb_ignore(env, 1);
+
diff --git a/target-lm32/TODO b/target-lm32/TODO
new file mode 100644
index 0000000..b9ea0c8
--- /dev/null
+++ b/target-lm32/TODO
@@ -0,0 +1,3 @@
+* disassembler (lm32-dis.c)
+* linux-user emulation
+* native bp/wp emulation (?)
commit d821732abac6501f3bd4d30c9deeb3ccba8b14e7
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:14 2011 +0100

    lm32: EVR32 and uclinux BSP
    
    This patch adds support for the following two BSPs:
     - LM32 EVR32 BSP (as used by RTEMS)
     - uclinux BSP by Theobroma Systems
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 35cca55..f0df98e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -247,6 +247,9 @@ obj-ppc-y += xilinx_timer.o
 obj-ppc-y += xilinx_uartlite.o
 obj-ppc-y += xilinx_ethlite.o
 
+# LM32 boards
+obj-lm32-y += lm32_boards.o
+
 # LM32 peripherals
 obj-lm32-y += lm32_pic.o
 obj-lm32-y += lm32_juart.o
diff --git a/default-configs/lm32-softmmu.mak b/default-configs/lm32-softmmu.mak
new file mode 100644
index 0000000..ab774a2
--- /dev/null
+++ b/default-configs/lm32-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for lm32-softmmu
+
+CONFIG_PTIMER=y
+CONFIG_PFLASH_CFI02=y
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
new file mode 100644
index 0000000..85190f0
--- /dev/null
+++ b/hw/lm32_boards.c
@@ -0,0 +1,305 @@
+/*
+ *  QEMU models for LatticeMico32 uclinux and evr32 boards.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+#include "net.h"
+#include "flash.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "loader.h"
+#include "blockdev.h"
+#include "elf.h"
+#include "lm32_hwsetup.h"
+#include "lm32.h"
+
+typedef struct {
+    CPUState *env;
+    target_phys_addr_t bootstrap_pc;
+    target_phys_addr_t flash_base;
+    target_phys_addr_t hwsetup_base;
+    target_phys_addr_t initrd_base;
+    size_t initrd_size;
+    target_phys_addr_t cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPUState *env = opaque;
+
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetInfo *reset_info = opaque;
+    CPUState *env = reset_info->env;
+
+    cpu_reset(env);
+
+    /* init defaults */
+    env->pc = (uint32_t)reset_info->bootstrap_pc;
+    env->regs[R_R1] = (uint32_t)reset_info->hwsetup_base;
+    env->regs[R_R2] = (uint32_t)reset_info->cmdline_base;
+    env->regs[R_R3] = (uint32_t)reset_info->initrd_base;
+    env->regs[R_R4] = (uint32_t)(reset_info->initrd_base +
+        reset_info->initrd_size);
+    env->eba = reset_info->flash_base;
+    env->deba = reset_info->flash_base;
+}
+
+static void lm32_evr_init(ram_addr_t ram_size_not_used,
+                          const char *boot_device,
+                          const char *kernel_filename,
+                          const char *kernel_cmdline,
+                          const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env;
+    DriveInfo *dinfo;
+    ram_addr_t phys_ram;
+    ram_addr_t phys_flash;
+    qemu_irq *cpu_irq, irq[32];
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    target_phys_addr_t flash_base  = 0x04000000;
+    size_t flash_sector_size       = 256 * 1024;
+    size_t flash_size              = 32 * 1024 * 1024;
+    target_phys_addr_t ram_base    = 0x08000000;
+    size_t ram_size                = 64 * 1024 * 1024;
+    target_phys_addr_t timer0_base = 0x80002000;
+    target_phys_addr_t uart0_base  = 0x80006000;
+    target_phys_addr_t timer1_base = 0x8000a000;
+    int uart0_irq                  = 0;
+    int timer0_irq                 = 1;
+    int timer1_irq                 = 3;
+
+    reset_info = qemu_mallocz(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    env = cpu_init(cpu_model);
+    reset_info->env = env;
+
+    reset_info->flash_base = flash_base;
+
+    phys_ram = qemu_ram_alloc(NULL, "lm32_evr.sdram", ram_size);
+    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+
+    phys_flash = qemu_ram_alloc(NULL, "lm32_evr.flash", flash_size);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, phys_flash,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 1, 2,
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
+    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
+    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    reset_info->bootstrap_pc = flash_base;
+
+    if (kernel_filename) {
+        uint64_t entry;
+        int kernel_size;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ram_base,
+                                              ram_size);
+            reset_info->bootstrap_pc = ram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static void lm32_uclinux_init(ram_addr_t ram_size_not_used,
+                          const char *boot_device,
+                          const char *kernel_filename,
+                          const char *kernel_cmdline,
+                          const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env;
+    DriveInfo *dinfo;
+    ram_addr_t phys_ram;
+    ram_addr_t phys_flash;
+    qemu_irq *cpu_irq, irq[32];
+    HWSetup *hw;
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    target_phys_addr_t flash_base   = 0x04000000;
+    size_t flash_sector_size        = 256 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    target_phys_addr_t ram_base     = 0x08000000;
+    size_t ram_size                 = 64 * 1024 * 1024;
+    target_phys_addr_t uart0_base   = 0x80000000;
+    target_phys_addr_t timer0_base  = 0x80002000;
+    target_phys_addr_t timer1_base  = 0x80010000;
+    target_phys_addr_t timer2_base  = 0x80012000;
+    int uart0_irq                   = 0;
+    int timer0_irq                  = 1;
+    int timer1_irq                  = 20;
+    int timer2_irq                  = 21;
+    target_phys_addr_t hwsetup_base = 0x0bffe000;
+    target_phys_addr_t cmdline_base = 0x0bfff000;
+    target_phys_addr_t initrd_base  = 0x08400000;
+    size_t initrd_max               = 0x01000000;
+
+    reset_info = qemu_mallocz(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    env = cpu_init(cpu_model);
+    reset_info->env = env;
+
+    reset_info->flash_base = flash_base;
+
+    phys_ram = qemu_ram_alloc(NULL, "lm32_uclinux.sdram", ram_size);
+    cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+
+    phys_flash = qemu_ram_alloc(NULL, "lm32_uclinux.flash", flash_size);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, phys_flash,
+                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
+                          flash_size / flash_sector_size, 1, 2,
+                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+
+    /* create irq lines */
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    env->pic_state = lm32_pic_init(*cpu_irq);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(env->pic_state, i);
+    }
+
+    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
+    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
+    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
+    sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);
+
+    /* make sure juart isn't the first chardev */
+    env->juart_state = lm32_juart_init();
+
+    reset_info->bootstrap_pc = flash_base;
+
+    if (kernel_filename) {
+        uint64_t entry;
+        int kernel_size;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1, ELF_MACHINE, 0);
+        reset_info->bootstrap_pc = entry;
+
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename, ram_base,
+                                              ram_size);
+            reset_info->bootstrap_pc = ram_base;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* generate a rom with the hardware description */
+    hw = hwsetup_init();
+    hwsetup_add_cpu(hw, "LM32", 75000000);
+    hwsetup_add_flash(hw, "flash", flash_base, flash_size);
+    hwsetup_add_ddr_sdram(hw, "ddr_sdram", ram_base, ram_size);
+    hwsetup_add_timer(hw, "timer0", timer0_base, timer0_irq);
+    hwsetup_add_timer(hw, "timer1_dev_only", timer1_base, timer1_irq);
+    hwsetup_add_timer(hw, "timer2_dev_only", timer2_base, timer2_irq);
+    hwsetup_add_uart(hw, "uart", uart0_base, uart0_irq);
+    hwsetup_add_trailer(hw);
+    hwsetup_create_rom(hw, hwsetup_base);
+    hwsetup_free(hw);
+
+    reset_info->hwsetup_base = hwsetup_base;
+
+    if (kernel_cmdline && strlen(kernel_cmdline)) {
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
+                kernel_cmdline);
+        reset_info->cmdline_base = cmdline_base;
+    }
+
+    if (initrd_filename) {
+        size_t initrd_size;
+        initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                initrd_max);
+        reset_info->initrd_base = initrd_base;
+        reset_info->initrd_size = initrd_size;
+    }
+
+    qemu_register_reset(main_cpu_reset, reset_info);
+}
+
+static QEMUMachine lm32_evr_machine = {
+    .name = "lm32-evr",
+    .desc = "LatticeMico32 EVR32 eval system",
+    .init = lm32_evr_init,
+    .is_default = 1
+};
+
+static QEMUMachine lm32_uclinux_machine = {
+    .name = "lm32-uclinux",
+    .desc = "lm32 platform for uClinux and u-boot by Theobroma Systems",
+    .init = lm32_uclinux_init,
+    .is_default = 0
+};
+
+static void lm32_machine_init(void)
+{
+    qemu_register_machine(&lm32_uclinux_machine);
+    qemu_register_machine(&lm32_evr_machine);
+}
+
+machine_init(lm32_machine_init);
commit e5f799a26764e4d2a86e14a3adb5c850e4eeb099
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:13 2011 +0100

    lm32: support for creating device tree
    
    This patch adds helper functions to create a ROM, which contains a hardware
    description of a board. This is used in Theobromas LM32 Linux port.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h
new file mode 100644
index 0000000..9f47821
--- /dev/null
+++ b/hw/lm32_hwsetup.h
@@ -0,0 +1,178 @@
+/*
+ *  LatticeMico32 hwsetup helper functions.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * These are helper functions for creating the hardware description blob used
+ * in the Theobroma's uClinux port.
+ */
+
+#ifndef QEMU_HW_LM32_HWSETUP_H
+#define QEMU_HW_LM32_HWSETUP_H
+
+#include "qemu-common.h"
+#include "loader.h"
+
+typedef struct {
+    void *data;
+    void *ptr;
+} HWSetup;
+
+enum hwsetup_tag {
+    HWSETUP_TAG_EOL         = 0,
+    HWSETUP_TAG_CPU         = 1,
+    HWSETUP_TAG_ASRAM       = 2,
+    HWSETUP_TAG_FLASH       = 3,
+    HWSETUP_TAG_SDRAM       = 4,
+    HWSETUP_TAG_OCM         = 5,
+    HWSETUP_TAG_DDR_SDRAM   = 6,
+    HWSETUP_TAG_DDR2_SDRAM  = 7,
+    HWSETUP_TAG_TIMER       = 8,
+    HWSETUP_TAG_UART        = 9,
+    HWSETUP_TAG_GPIO        = 10,
+    HWSETUP_TAG_TRISPEEDMAC = 11,
+    HWSETUP_TAG_I2CM        = 12,
+    HWSETUP_TAG_LEDS        = 13,
+    HWSETUP_TAG_7SEG        = 14,
+    HWSETUP_TAG_SPI_S       = 15,
+    HWSETUP_TAG_SPI_M       = 16,
+};
+
+static inline HWSetup *hwsetup_init(void)
+{
+    HWSetup *hw;
+
+    hw = qemu_malloc(sizeof(HWSetup));
+    hw->data = qemu_mallocz(TARGET_PAGE_SIZE);
+    hw->ptr = hw->data;
+
+    return hw;
+}
+
+static inline void hwsetup_free(HWSetup *hw)
+{
+    qemu_free(hw->data);
+    qemu_free(hw);
+}
+
+static inline void hwsetup_create_rom(HWSetup *hw,
+        target_phys_addr_t base)
+{
+    rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base);
+}
+
+static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)
+{
+    stb_p(hw->ptr, u);
+    hw->ptr += 1;
+}
+
+static inline void hwsetup_add_u32(HWSetup *hw, uint32_t u)
+{
+    stl_p(hw->ptr, u);
+    hw->ptr += 4;
+}
+
+static inline void hwsetup_add_tag(HWSetup *hw, enum hwsetup_tag t)
+{
+    stl_p(hw->ptr, t);
+    hw->ptr += 4;
+}
+
+static inline void hwsetup_add_str(HWSetup *hw, const char *str)
+{
+    strncpy(hw->ptr, str, 31); /* make sure last byte is zero */
+    hw->ptr += 32;
+}
+
+static inline void hwsetup_add_trailer(HWSetup *hw)
+{
+    hwsetup_add_u32(hw, 8); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_EOL);
+}
+
+static inline void hwsetup_add_cpu(HWSetup *hw,
+        const char *name, uint32_t frequency)
+{
+    hwsetup_add_u32(hw, 44); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_CPU);
+    hwsetup_add_str(hw, name);
+    hwsetup_add_u32(hw, frequency);
+}
+
+static inline void hwsetup_add_flash(HWSetup *hw,
+        const char *name, uint32_t base, uint32_t size)
+{
+    hwsetup_add_u32(hw, 52); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_FLASH);
+    hwsetup_add_str(hw, name);
+    hwsetup_add_u32(hw, base);
+    hwsetup_add_u32(hw, size);
+    hwsetup_add_u8(hw, 8); /* read latency */
+    hwsetup_add_u8(hw, 8); /* write latency */
+    hwsetup_add_u8(hw, 25); /* address width */
+    hwsetup_add_u8(hw, 32); /* data width */
+}
+
+static inline void hwsetup_add_ddr_sdram(HWSetup *hw,
+        const char *name, uint32_t base, uint32_t size)
+{
+    hwsetup_add_u32(hw, 48); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_DDR_SDRAM);
+    hwsetup_add_str(hw, name);
+    hwsetup_add_u32(hw, base);
+    hwsetup_add_u32(hw, size);
+}
+
+static inline void hwsetup_add_timer(HWSetup *hw,
+        const char *name, uint32_t base, uint32_t irq)
+{
+    hwsetup_add_u32(hw, 56); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_TIMER);
+    hwsetup_add_str(hw, name);
+    hwsetup_add_u32(hw, base);
+    hwsetup_add_u8(hw, 1); /* wr_tickcount */
+    hwsetup_add_u8(hw, 1); /* rd_tickcount */
+    hwsetup_add_u8(hw, 1); /* start_stop_control */
+    hwsetup_add_u8(hw, 32); /* counter_width */
+    hwsetup_add_u32(hw, 20); /* reload_ticks */
+    hwsetup_add_u8(hw, irq);
+    hwsetup_add_u8(hw, 0); /* padding */
+    hwsetup_add_u8(hw, 0); /* padding */
+    hwsetup_add_u8(hw, 0); /* padding */
+}
+
+static inline void hwsetup_add_uart(HWSetup *hw,
+        const char *name, uint32_t base, uint32_t irq)
+{
+    hwsetup_add_u32(hw, 56); /* size */
+    hwsetup_add_tag(hw, HWSETUP_TAG_UART);
+    hwsetup_add_str(hw, name);
+    hwsetup_add_u32(hw, base);
+    hwsetup_add_u32(hw, 115200); /* baudrate */
+    hwsetup_add_u8(hw, 8); /* databits */
+    hwsetup_add_u8(hw, 1); /* stopbits */
+    hwsetup_add_u8(hw, 1); /* use_interrupt */
+    hwsetup_add_u8(hw, 1); /* block_on_transmit */
+    hwsetup_add_u8(hw, 1); /* block_on_receive */
+    hwsetup_add_u8(hw, 4); /* rx_buffer_size */
+    hwsetup_add_u8(hw, 4); /* tx_buffer_size */
+    hwsetup_add_u8(hw, irq);
+}
+
+#endif /* QEMU_HW_LM32_HWSETUP_H */
commit f19410ca691ddf5112eaefb30f7cea3ac3e713a4
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:12 2011 +0100

    lm32: system control model
    
    This patch add support for a system control block. It is supposed to
    act as helper for the emulated program. E.g. shutting down the VM or
    printing test results. This model is intended for testing purposes only and
    doesn't fit to any real hardware. Therefore, it is not added to any board
    by default. Instead a user has to add it explicitly with the '-device'
    commandline parameter.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index d669d25..35cca55 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -252,6 +252,7 @@ obj-lm32-y += lm32_pic.o
 obj-lm32-y += lm32_juart.o
 obj-lm32-y += lm32_timer.o
 obj-lm32-y += lm32_uart.o
+obj-lm32-y += lm32_sys.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
new file mode 100644
index 0000000..427b05f
--- /dev/null
+++ b/hw/lm32_sys.c
@@ -0,0 +1,161 @@
+/*
+ *  QEMU model of the LatticeMico32 system control block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This model is mainly intended for testing purposes and doesn't fit to any
+ * real hardware. On the one hand it provides a control register (R_CTRL) on
+ * the other hand it supports the lm32 tests.
+ *
+ * A write to the control register causes a system shutdown.
+ * Tests first write the pointer to a test name to the test name register
+ * (R_TESTNAME) and then write a zero to the pass/fail register (R_PASSFAIL) if
+ * the test is passed or any non-zero value to it if the test is failed.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-log.h"
+#include "qemu-error.h"
+#include "sysemu.h"
+#include "qemu-log.h"
+
+enum {
+    R_CTRL = 0,
+    R_PASSFAIL,
+    R_TESTNAME,
+    R_MAX
+};
+
+#define MAX_TESTNAME_LEN 16
+
+struct LM32SysState {
+    SysBusDevice busdev;
+    uint32_t base;
+    uint32_t regs[R_MAX];
+    uint8_t testname[MAX_TESTNAME_LEN];
+};
+typedef struct LM32SysState LM32SysState;
+
+static void copy_testname(LM32SysState *s)
+{
+    cpu_physical_memory_read(s->regs[R_TESTNAME], s->testname,
+            MAX_TESTNAME_LEN);
+    s->testname[MAX_TESTNAME_LEN - 1] = '\0';
+}
+
+static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    LM32SysState *s = opaque;
+    char *testname;
+
+    trace_lm32_sys_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_CTRL:
+        qemu_system_shutdown_request();
+        break;
+    case R_PASSFAIL:
+        s->regs[addr] = value;
+        testname = (char *)s->testname;
+        qemu_log("TC  %-16s %s\n", testname, (value) ? "FAILED" : "OK");
+        break;
+    case R_TESTNAME:
+        s->regs[addr] = value;
+        copy_testname(s);
+        break;
+
+    default:
+        error_report("lm32_sys: write access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc * const sys_read_fn[] = {
+    NULL,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc * const sys_write_fn[] = {
+    NULL,
+    NULL,
+    &sys_write,
+};
+
+static void sys_reset(DeviceState *d)
+{
+    LM32SysState *s = container_of(d, LM32SysState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    memset(s->testname, 0, MAX_TESTNAME_LEN);
+}
+
+static int lm32_sys_init(SysBusDevice *dev)
+{
+    LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
+    int sys_regs;
+
+    sys_regs = cpu_register_io_memory(sys_read_fn, sys_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, sys_regs);
+
+    /* Note: This device is not created in the board initialization,
+     * instead it has to be added with the -device parameter. Therefore,
+     * the device maps itself. */
+    sysbus_mmio_map(dev, 0, s->base);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_lm32_sys = {
+    .name = "lm32-sys",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, LM32SysState, R_MAX),
+        VMSTATE_BUFFER(testname, LM32SysState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo lm32_sys_info = {
+    .init = lm32_sys_init,
+    .qdev.name  = "lm32-sys",
+    .qdev.size  = sizeof(LM32SysState),
+    .qdev.vmsd  = &vmstate_lm32_sys,
+    .qdev.reset = sys_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void lm32_sys_register(void)
+{
+    sysbus_register_withprop(&lm32_sys_info);
+}
+
+device_init(lm32_sys_register)
diff --git a/trace-events b/trace-events
index 90bbbc1..c791719 100644
--- a/trace-events
+++ b/trace-events
@@ -280,3 +280,6 @@ disable lm32_timer_irq_state(int level) "irq state %d"
 disable lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 disable lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 disable lm32_uart_irq_state(int level) "irq state %d"
+
+# hw/lm32_sys.c
+disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
commit 770ae5713af30e42492581fd53000a1b4a92a3c7
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:11 2011 +0100

    lm32: uart model
    
    This patch add support for the LatticeMico32 UART.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index e4e8281..d669d25 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -251,6 +251,7 @@ obj-ppc-y += xilinx_ethlite.o
 obj-lm32-y += lm32_pic.o
 obj-lm32-y += lm32_juart.o
 obj-lm32-y += lm32_timer.o
+obj-lm32-y += lm32_uart.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
new file mode 100644
index 0000000..e225087
--- /dev/null
+++ b/hw/lm32_uart.c
@@ -0,0 +1,288 @@
+/*
+ *  QEMU model of the LatticeMico32 UART block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.latticesemi.com/documents/mico32uart.pdf
+ */
+
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-char.h"
+#include "qemu-error.h"
+
+enum {
+    R_RXTX = 0,
+    R_IER,
+    R_IIR,
+    R_LCR,
+    R_MCR,
+    R_LSR,
+    R_MSR,
+    R_DIV,
+    R_MAX
+};
+
+enum {
+    IER_RBRI = (1<<0),
+    IER_THRI = (1<<1),
+    IER_RLSI = (1<<2),
+    IER_MSI  = (1<<3),
+};
+
+enum {
+    IIR_STAT = (1<<0),
+    IIR_ID0  = (1<<1),
+    IIR_ID1  = (1<<2),
+};
+
+enum {
+    LCR_WLS0 = (1<<0),
+    LCR_WLS1 = (1<<1),
+    LCR_STB  = (1<<2),
+    LCR_PEN  = (1<<3),
+    LCR_EPS  = (1<<4),
+    LCR_SP   = (1<<5),
+    LCR_SB   = (1<<6),
+};
+
+enum {
+    MCR_DTR  = (1<<0),
+    MCR_RTS  = (1<<1),
+};
+
+enum {
+    LSR_DR   = (1<<0),
+    LSR_OE   = (1<<1),
+    LSR_PE   = (1<<2),
+    LSR_FE   = (1<<3),
+    LSR_BI   = (1<<4),
+    LSR_THRE = (1<<5),
+    LSR_TEMT = (1<<6),
+};
+
+enum {
+    MSR_DCTS = (1<<0),
+    MSR_DDSR = (1<<1),
+    MSR_TERI = (1<<2),
+    MSR_DDCD = (1<<3),
+    MSR_CTS  = (1<<4),
+    MSR_DSR  = (1<<5),
+    MSR_RI   = (1<<6),
+    MSR_DCD  = (1<<7),
+};
+
+struct LM32UartState {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint32_t regs[R_MAX];
+};
+typedef struct LM32UartState LM32UartState;
+
+static void uart_update_irq(LM32UartState *s)
+{
+    unsigned int irq;
+
+    if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI))
+            && (s->regs[R_IER] & IER_RLSI)) {
+        irq = 1;
+        s->regs[R_IIR] = IIR_ID1 | IIR_ID0;
+    } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) {
+        irq = 1;
+        s->regs[R_IIR] = IIR_ID1;
+    } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) {
+        irq = 1;
+        s->regs[R_IIR] = IIR_ID0;
+    } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) {
+        irq = 1;
+        s->regs[R_IIR] = 0;
+    } else {
+        irq = 0;
+        s->regs[R_IIR] = IIR_STAT;
+    }
+
+    trace_lm32_uart_irq_state(irq);
+    qemu_set_irq(s->irq, irq);
+}
+
+static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
+{
+    LM32UartState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_RXTX:
+        r = s->regs[R_RXTX];
+        s->regs[R_LSR] &= ~LSR_DR;
+        uart_update_irq(s);
+        break;
+    case R_IIR:
+    case R_LSR:
+    case R_MSR:
+        r = s->regs[addr];
+        break;
+    case R_IER:
+    case R_LCR:
+    case R_MCR:
+    case R_DIV:
+        error_report("lm32_uart: read access to write only register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    default:
+        error_report("lm32_uart: read access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_lm32_uart_memory_read(addr << 2, r);
+    return r;
+}
+
+static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    LM32UartState *s = opaque;
+    unsigned char ch = value;
+
+    trace_lm32_uart_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_RXTX:
+        if (s->chr) {
+            qemu_chr_write(s->chr, &ch, 1);
+        }
+        break;
+    case R_IER:
+    case R_LCR:
+    case R_MCR:
+    case R_DIV:
+        s->regs[addr] = value;
+        break;
+    case R_IIR:
+    case R_LSR:
+    case R_MSR:
+        error_report("lm32_uart: write access to read only register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    default:
+        error_report("lm32_uart: write access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+    uart_update_irq(s);
+}
+
+static CPUReadMemoryFunc * const uart_read_fn[] = {
+    NULL,
+    NULL,
+    &uart_read,
+};
+
+static CPUWriteMemoryFunc * const uart_write_fn[] = {
+    NULL,
+    NULL,
+    &uart_write,
+};
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+    LM32UartState *s = opaque;
+
+    if (s->regs[R_LSR] & LSR_DR) {
+        s->regs[R_LSR] |= LSR_OE;
+    }
+
+    s->regs[R_LSR] |= LSR_DR;
+    s->regs[R_RXTX] = *buf;
+
+    uart_update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)
+{
+    LM32UartState *s = opaque;
+
+    return !(s->regs[R_LSR] & LSR_DR);
+}
+
+static void uart_event(void *opaque, int event)
+{
+}
+
+static void uart_reset(DeviceState *d)
+{
+    LM32UartState *s = container_of(d, LM32UartState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    /* defaults */
+    s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
+}
+
+static int lm32_uart_init(SysBusDevice *dev)
+{
+    LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
+    int uart_regs;
+
+    sysbus_init_irq(dev, &s->irq);
+
+    uart_regs = cpu_register_io_memory(uart_read_fn, uart_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+
+    s->chr = qdev_init_chardev(&dev->qdev);
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_lm32_uart = {
+    .name = "lm32-uart",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo lm32_uart_info = {
+    .init = lm32_uart_init,
+    .qdev.name  = "lm32-uart",
+    .qdev.size  = sizeof(LM32UartState),
+    .qdev.vmsd  = &vmstate_lm32_uart,
+    .qdev.reset = uart_reset,
+};
+
+static void lm32_uart_register(void)
+{
+    sysbus_register_withprop(&lm32_uart_info);
+}
+
+device_init(lm32_uart_register)
diff --git a/trace-events b/trace-events
index af7b27f..90bbbc1 100644
--- a/trace-events
+++ b/trace-events
@@ -275,3 +275,8 @@ disable lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x valu
 disable lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 disable lm32_timer_hit(void) "timer hit"
 disable lm32_timer_irq_state(int level) "irq state %d"
+
+# hw/lm32_uart.c
+disable lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+disable lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+disable lm32_uart_irq_state(int level) "irq state %d"
commit ea7924dcc4000643ad767fa106a15acb9f8e055b
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:10 2011 +0100

    lm32: timer model
    
    This patch adds support for the LatticeMico32 system timer.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index c1fcc5b..e4e8281 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -250,6 +250,7 @@ obj-ppc-y += xilinx_ethlite.o
 # LM32 peripherals
 obj-lm32-y += lm32_pic.o
 obj-lm32-y += lm32_juart.o
+obj-lm32-y += lm32_timer.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
new file mode 100644
index 0000000..ed28984
--- /dev/null
+++ b/hw/lm32_timer.c
@@ -0,0 +1,222 @@
+/*
+ *  QEMU model of the LatticeMico32 timer block.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.latticesemi.com/documents/mico32timer.pdf
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-timer.h"
+#include "qemu-error.h"
+
+#define DEFAULT_FREQUENCY (50*1000000)
+
+enum {
+    R_SR = 0,
+    R_CR,
+    R_PERIOD,
+    R_SNAPSHOT,
+    R_MAX
+};
+
+enum {
+    SR_TO    = (1 << 0),
+    SR_RUN   = (1 << 1),
+};
+
+enum {
+    CR_ITO   = (1 << 0),
+    CR_CONT  = (1 << 1),
+    CR_START = (1 << 2),
+    CR_STOP  = (1 << 3),
+};
+
+struct LM32TimerState {
+    SysBusDevice busdev;
+
+    QEMUBH *bh;
+    ptimer_state *ptimer;
+
+    qemu_irq irq;
+    uint32_t freq_hz;
+
+    uint32_t regs[R_MAX];
+};
+typedef struct LM32TimerState LM32TimerState;
+
+static void timer_update_irq(LM32TimerState *s)
+{
+    int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO);
+
+    trace_lm32_timer_irq_state(state);
+    qemu_set_irq(s->irq, state);
+}
+
+static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
+{
+    LM32TimerState *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SR:
+    case R_CR:
+    case R_PERIOD:
+        r = s->regs[addr];
+        break;
+    case R_SNAPSHOT:
+        r = (uint32_t)ptimer_get_count(s->ptimer);
+        break;
+    default:
+        error_report("lm32_timer: read access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_lm32_timer_memory_read(addr << 2, r);
+    return r;
+}
+
+static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    LM32TimerState *s = opaque;
+
+    trace_lm32_timer_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SR:
+        s->regs[R_SR] &= ~SR_TO;
+        break;
+    case R_CR:
+        s->regs[R_CR] = value;
+        if (s->regs[R_CR] & CR_START) {
+            ptimer_run(s->ptimer, 1);
+        }
+        if (s->regs[R_CR] & CR_STOP) {
+            ptimer_stop(s->ptimer);
+        }
+        break;
+    case R_PERIOD:
+        s->regs[R_PERIOD] = value;
+        ptimer_set_count(s->ptimer, value);
+        break;
+    case R_SNAPSHOT:
+        error_report("lm32_timer: write access to read only register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    default:
+        error_report("lm32_timer: write access to unkown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+    timer_update_irq(s);
+}
+
+static CPUReadMemoryFunc * const timer_read_fn[] = {
+    NULL,
+    NULL,
+    &timer_read,
+};
+
+static CPUWriteMemoryFunc * const timer_write_fn[] = {
+    NULL,
+    NULL,
+    &timer_write,
+};
+
+static void timer_hit(void *opaque)
+{
+    LM32TimerState *s = opaque;
+
+    trace_lm32_timer_hit();
+
+    s->regs[R_SR] |= SR_TO;
+
+    if (s->regs[R_CR] & CR_CONT) {
+        ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
+        ptimer_run(s->ptimer, 1);
+    }
+    timer_update_irq(s);
+}
+
+static void timer_reset(DeviceState *d)
+{
+    LM32TimerState *s = container_of(d, LM32TimerState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+    ptimer_stop(s->ptimer);
+}
+
+static int lm32_timer_init(SysBusDevice *dev)
+{
+    LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev);
+    int timer_regs;
+
+    sysbus_init_irq(dev, &s->irq);
+
+    s->bh = qemu_bh_new(timer_hit, s);
+    s->ptimer = ptimer_init(s->bh);
+    ptimer_set_freq(s->ptimer, s->freq_hz);
+
+    timer_regs = cpu_register_io_memory(timer_read_fn, timer_write_fn, s,
+            DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, R_MAX * 4, timer_regs);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_lm32_timer = {
+    .name = "lm32-timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PTIMER(ptimer, LM32TimerState),
+        VMSTATE_UINT32(freq_hz, LM32TimerState),
+        VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo lm32_timer_info = {
+    .init = lm32_timer_init,
+    .qdev.name  = "lm32-timer",
+    .qdev.size  = sizeof(LM32TimerState),
+    .qdev.vmsd  = &vmstate_lm32_timer,
+    .qdev.reset = timer_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32(
+                "frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY
+        ),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void lm32_timer_register(void)
+{
+    sysbus_register_withprop(&lm32_timer_info);
+}
+
+device_init(lm32_timer_register)
diff --git a/trace-events b/trace-events
index 966099f..af7b27f 100644
--- a/trace-events
+++ b/trace-events
@@ -269,3 +269,9 @@ disable lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x"
 disable lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x"
 disable lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x"
 disable lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x"
+
+# hw/lm32_timer.c
+disable lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+disable lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+disable lm32_timer_hit(void) "timer hit"
+disable lm32_timer_irq_state(int level) "irq state %d"
commit f89286ae45973e00189da67f28264ade74a645e2
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:09 2011 +0100

    lm32: pic and juart helper functions
    
    This patch adds init functions for the PIC and JTAG UART commonly used
    in the board initialization.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/lm32.h b/hw/lm32.h
new file mode 100644
index 0000000..0a67632
--- /dev/null
+++ b/hw/lm32.h
@@ -0,0 +1,25 @@
+
+#include "qemu-common.h"
+
+static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *d;
+
+    dev = qdev_create(NULL, "lm32-pic");
+    qdev_init_nofail(dev);
+    d = sysbus_from_qdev(dev);
+    sysbus_connect_irq(d, 0, cpu_irq);
+
+    return dev;
+}
+
+static inline DeviceState *lm32_juart_init(void)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "lm32-juart");
+    qdev_init_nofail(dev);
+
+    return dev;
+}
commit 15d7dc4f8086b9d0a09fbcf28ee1654a210351dd
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:08 2011 +0100

    lm32: juart model
    
    This patch adds the JTAG UART model. It is accessed through special control
    registers and opcodes. Therefore the translation uses callbacks to this
    model.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index a6e7e5a..c1fcc5b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -249,6 +249,7 @@ obj-ppc-y += xilinx_ethlite.o
 
 # LM32 peripherals
 obj-lm32-y += lm32_pic.o
+obj-lm32-y += lm32_juart.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
new file mode 100644
index 0000000..fddcf7e
--- /dev/null
+++ b/hw/lm32_juart.c
@@ -0,0 +1,150 @@
+/*
+ *  LatticeMico32 JTAG UART model.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "qemu-char.h"
+
+#include "lm32_juart.h"
+
+enum {
+    LM32_JUART_MIN_SAVE_VERSION = 0,
+    LM32_JUART_CURRENT_SAVE_VERSION = 0,
+    LM32_JUART_MAX_SAVE_VERSION = 0,
+};
+
+enum {
+    JTX_FULL = (1<<8),
+};
+
+enum {
+    JRX_FULL = (1<<8),
+};
+
+struct LM32JuartState {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+
+    uint32_t jtx;
+    uint32_t jrx;
+};
+typedef struct LM32JuartState LM32JuartState;
+
+uint32_t lm32_juart_get_jtx(DeviceState *d)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    trace_lm32_juart_get_jtx(s->jtx);
+    return s->jtx;
+}
+
+uint32_t lm32_juart_get_jrx(DeviceState *d)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    trace_lm32_juart_get_jrx(s->jrx);
+    return s->jrx;
+}
+
+void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+    unsigned char ch = jtx & 0xff;
+
+    trace_lm32_juart_set_jtx(s->jtx);
+
+    s->jtx = jtx;
+    if (s->chr) {
+        qemu_chr_write(s->chr, &ch, 1);
+    }
+}
+
+void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    trace_lm32_juart_set_jrx(s->jrx);
+    s->jrx &= ~JRX_FULL;
+}
+
+static void juart_rx(void *opaque, const uint8_t *buf, int size)
+{
+    LM32JuartState *s = opaque;
+
+    s->jrx = *buf | JRX_FULL;
+}
+
+static int juart_can_rx(void *opaque)
+{
+    LM32JuartState *s = opaque;
+
+    return !(s->jrx & JRX_FULL);
+}
+
+static void juart_event(void *opaque, int event)
+{
+}
+
+static void juart_reset(DeviceState *d)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    s->jtx = 0;
+    s->jrx = 0;
+}
+
+static int lm32_juart_init(SysBusDevice *dev)
+{
+    LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    s->chr = qdev_init_chardev(&dev->qdev);
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_lm32_juart = {
+    .name = "lm32-juart",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(jtx, LM32JuartState),
+        VMSTATE_UINT32(jrx, LM32JuartState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo lm32_juart_info = {
+    .init = lm32_juart_init,
+    .qdev.name  = "lm32-juart",
+    .qdev.size  = sizeof(LM32JuartState),
+    .qdev.vmsd  = &vmstate_lm32_juart,
+    .qdev.reset = juart_reset,
+};
+
+static void lm32_juart_register(void)
+{
+    sysbus_register_withprop(&lm32_juart_info);
+}
+
+device_init(lm32_juart_register)
diff --git a/hw/lm32_juart.h b/hw/lm32_juart.h
new file mode 100644
index 0000000..67fc586
--- /dev/null
+++ b/hw/lm32_juart.h
@@ -0,0 +1,11 @@
+#ifndef QEMU_HW_LM32_JUART_H
+#define QEMU_HW_LM32_JUART_H
+
+#include "qemu-common.h"
+
+uint32_t lm32_juart_get_jtx(DeviceState *d);
+uint32_t lm32_juart_get_jrx(DeviceState *d);
+void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx);
+void lm32_juart_set_jrx(DeviceState *d, uint32_t jrx);
+
+#endif /* QEMU_HW_LM32_JUART_H */
diff --git a/trace-events b/trace-events
index 557375e..966099f 100644
--- a/trace-events
+++ b/trace-events
@@ -263,3 +263,9 @@ disable lm32_pic_set_im(uint32_t im) "im 0x%08x"
 disable lm32_pic_set_ip(uint32_t ip) "ip 0x%08x"
 disable lm32_pic_get_im(uint32_t im) "im 0x%08x"
 disable lm32_pic_get_ip(uint32_t ip) "ip 0x%08x"
+
+# hw/lm32_juart.c
+disable lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x"
+disable lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x"
+disable lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x"
+disable lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x"
commit 4ef66fa71882a8f8682d9a8d1528e1ec98c264e5
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:07 2011 +0100

    lm32: interrupt controller model
    
    This patch adds the interrupt controller of the lm32. Because the PIC is
    accessed through special control registers and opcodes, there are callbacks
    from the lm32 translation code to this model.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 857976a..a6e7e5a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -248,6 +248,7 @@ obj-ppc-y += xilinx_uartlite.o
 obj-ppc-y += xilinx_ethlite.o
 
 # LM32 peripherals
+obj-lm32-y += lm32_pic.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
new file mode 100644
index 0000000..02941a7
--- /dev/null
+++ b/hw/lm32_pic.c
@@ -0,0 +1,190 @@
+/*
+ *  LatticeMico32 CPU interrupt controller logic.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "hw.h"
+#include "pc.h"
+#include "monitor.h"
+#include "sysbus.h"
+#include "trace.h"
+#include "lm32_pic.h"
+
+struct LM32PicState {
+    SysBusDevice busdev;
+    qemu_irq parent_irq;
+    uint32_t im;        /* interrupt mask */
+    uint32_t ip;        /* interrupt pending */
+    uint32_t irq_state;
+
+    /* statistics */
+    uint32_t stats_irq_count[32];
+};
+typedef struct LM32PicState LM32PicState;
+
+static LM32PicState *pic;
+void pic_info(Monitor *mon)
+{
+    if (pic == NULL) {
+        return;
+    }
+
+    monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n",
+            pic->im, pic->ip, pic->irq_state);
+}
+
+void irq_info(Monitor *mon)
+{
+    int i;
+    uint32_t count;
+
+    if (pic == NULL) {
+        return;
+    }
+
+    monitor_printf(mon, "IRQ statistics:\n");
+    for (i = 0; i < 32; i++) {
+        count = pic->stats_irq_count[i];
+        if (count > 0) {
+            monitor_printf(mon, "%2d: %u\n", i, count);
+        }
+    }
+}
+
+static void update_irq(LM32PicState *s)
+{
+    s->ip |= s->irq_state;
+
+    if (s->ip & s->im) {
+        trace_lm32_pic_raise_irq();
+        qemu_irq_raise(s->parent_irq);
+    } else {
+        trace_lm32_pic_lower_irq();
+        qemu_irq_lower(s->parent_irq);
+    }
+}
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    LM32PicState *s = opaque;
+
+    assert(irq < 32);
+    trace_lm32_pic_interrupt(irq, level);
+
+    if (level) {
+        s->irq_state |= (1 << irq);
+        s->stats_irq_count[irq]++;
+    } else {
+        s->irq_state &= ~(1 << irq);
+    }
+
+    update_irq(s);
+}
+
+void lm32_pic_set_im(DeviceState *d, uint32_t im)
+{
+    LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+
+    trace_lm32_pic_set_im(im);
+    s->im = im;
+
+    update_irq(s);
+}
+
+void lm32_pic_set_ip(DeviceState *d, uint32_t ip)
+{
+    LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+
+    trace_lm32_pic_set_ip(ip);
+
+    /* ack interrupt */
+    s->ip &= ~ip;
+
+    update_irq(s);
+}
+
+uint32_t lm32_pic_get_im(DeviceState *d)
+{
+    LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+
+    trace_lm32_pic_get_im(s->im);
+    return s->im;
+}
+
+uint32_t lm32_pic_get_ip(DeviceState *d)
+{
+    LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+
+    trace_lm32_pic_get_ip(s->ip);
+    return s->ip;
+}
+
+static void pic_reset(DeviceState *d)
+{
+    LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+    int i;
+
+    s->im = 0;
+    s->ip = 0;
+    s->irq_state = 0;
+    for (i = 0; i < 32; i++) {
+        s->stats_irq_count[i] = 0;
+    }
+}
+
+static int lm32_pic_init(SysBusDevice *dev)
+{
+    LM32PicState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
+    sysbus_init_irq(dev, &s->parent_irq);
+
+    pic = s;
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_lm32_pic = {
+    .name = "lm32-pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(im, LM32PicState),
+        VMSTATE_UINT32(ip, LM32PicState),
+        VMSTATE_UINT32(irq_state, LM32PicState),
+        VMSTATE_UINT32_ARRAY(stats_irq_count, LM32PicState, 32),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo lm32_pic_info = {
+    .init = lm32_pic_init,
+    .qdev.name  = "lm32-pic",
+    .qdev.size  = sizeof(LM32PicState),
+    .qdev.vmsd  = &vmstate_lm32_pic,
+    .qdev.reset = pic_reset,
+};
+
+static void lm32_pic_register(void)
+{
+    sysbus_register_withprop(&lm32_pic_info);
+}
+
+device_init(lm32_pic_register)
diff --git a/hw/lm32_pic.h b/hw/lm32_pic.h
new file mode 100644
index 0000000..e6479b8
--- /dev/null
+++ b/hw/lm32_pic.h
@@ -0,0 +1,11 @@
+#ifndef QEMU_HW_LM32_PIC_H
+#define QEMU_HW_LM32_PIC_H
+
+#include "qemu-common.h"
+
+uint32_t lm32_pic_get_ip(DeviceState *d);
+uint32_t lm32_pic_get_im(DeviceState *d);
+void lm32_pic_set_ip(DeviceState *d, uint32_t ip);
+void lm32_pic_set_im(DeviceState *d, uint32_t im);
+
+#endif /* QEMU_HW_LM32_PIC_H */
diff --git a/trace-events b/trace-events
index e6138ea..557375e 100644
--- a/trace-events
+++ b/trace-events
@@ -254,3 +254,12 @@ disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd
 disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
 disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
 disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
+
+# hw/lm32_pic.c
+disable lm32_pic_raise_irq(void) "Raise CPU interrupt"
+disable lm32_pic_lower_irq(void) "Lower CPU interrupt"
+disable lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d"
+disable lm32_pic_set_im(uint32_t im) "im 0x%08x"
+disable lm32_pic_set_ip(uint32_t ip) "ip 0x%08x"
+disable lm32_pic_get_im(uint32_t im) "im 0x%08x"
+disable lm32_pic_get_ip(uint32_t ip) "ip 0x%08x"
commit 0c45d3d4b921e9639a2ce400a6afdb4d962a5805
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:06 2011 +0100

    lm32: gdbstub support
    
    This patch adds lm32 support to the gdbstub.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/gdbstub.c b/gdbstub.c
index ed51a8a..1e9f931 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1462,6 +1462,80 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
     return r;
 }
+#elif defined (TARGET_LM32)
+
+#include "hw/lm32_pic.h"
+#define NUM_CORE_REGS (32 + 7)
+
+static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 32) {
+        GET_REG32(env->regs[n]);
+    } else {
+        switch (n) {
+        case 32:
+            GET_REG32(env->pc);
+            break;
+        /* FIXME: put in right exception ID */
+        case 33:
+            GET_REG32(0);
+            break;
+        case 34:
+            GET_REG32(env->eba);
+            break;
+        case 35:
+            GET_REG32(env->deba);
+            break;
+        case 36:
+            GET_REG32(env->ie);
+            break;
+        case 37:
+            GET_REG32(lm32_pic_get_im(env->pic_state));
+            break;
+        case 38:
+            GET_REG32(lm32_pic_get_ip(env->pic_state));
+            break;
+        }
+    }
+    return 0;
+}
+
+static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    uint32_t tmp;
+
+    if (n > NUM_CORE_REGS) {
+        return 0;
+    }
+
+    tmp = ldl_p(mem_buf);
+
+    if (n < 32) {
+        env->regs[n] = tmp;
+    } else {
+        switch (n) {
+        case 32:
+            env->pc = tmp;
+            break;
+        case 34:
+            env->eba = tmp;
+            break;
+        case 35:
+            env->deba = tmp;
+            break;
+        case 36:
+            env->ie = tmp;
+            break;
+        case 37:
+            lm32_pic_set_im(env->pic_state, tmp);
+            break;
+        case 38:
+            lm32_pic_set_ip(env->pic_state, tmp);
+            break;
+        }
+    }
+    return 4;
+}
 #else
 
 #define NUM_CORE_REGS 0
@@ -1737,6 +1811,8 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #elif defined (TARGET_S390X)
     cpu_synchronize_state(s->c_cpu);
     s->c_cpu->psw.addr = pc;
+#elif defined (TARGET_LM32)
+    s->c_cpu->pc = pc;
 #endif
 }
 
commit c6af5693478caacafc58cbf454b71fa95d57db60
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:05 2011 +0100

    lm32: machine state loading/saving
    
    This patch adds support for saving and loading the processor state.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/machine.c b/target-lm32/machine.c
new file mode 100644
index 0000000..70ca52a
--- /dev/null
+++ b/target-lm32/machine.c
@@ -0,0 +1,33 @@
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+static const VMStateDescription vmstate_cpu = {
+    .name = "cpu",
+    .version_id = CPU_SAVE_VERSION,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, CPUState, 32),
+        VMSTATE_UINT32(pc, CPUState),
+        VMSTATE_UINT32(ie, CPUState),
+        VMSTATE_UINT32(icc, CPUState),
+        VMSTATE_UINT32(dcc, CPUState),
+        VMSTATE_UINT32(cc, CPUState),
+        VMSTATE_UINT32(eba, CPUState),
+        VMSTATE_UINT32(dc, CPUState),
+        VMSTATE_UINT32(deba, CPUState),
+        VMSTATE_UINT32_ARRAY(bp, CPUState, 4),
+        VMSTATE_UINT32_ARRAY(wp, CPUState, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+    vmstate_save_state(f, &vmstate_cpu, opaque);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
+}
commit 143e8951e40c7dfcc985801ac93a7e58e2e44985
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:04 2011 +0100

    lm32: translation code helper
    
    This patch adds translation helper functions.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/helper.h b/target-lm32/helper.h
new file mode 100644
index 0000000..9d335ef
--- /dev/null
+++ b/target-lm32/helper.h
@@ -0,0 +1,14 @@
+#include "def-helper.h"
+
+DEF_HELPER_1(raise_exception, void, i32)
+DEF_HELPER_0(hlt, void)
+DEF_HELPER_1(wcsr_im, void, i32)
+DEF_HELPER_1(wcsr_ip, void, i32)
+DEF_HELPER_1(wcsr_jtx, void, i32)
+DEF_HELPER_1(wcsr_jrx, void, i32)
+DEF_HELPER_0(rcsr_im, i32)
+DEF_HELPER_0(rcsr_ip, i32)
+DEF_HELPER_0(rcsr_jtx, i32)
+DEF_HELPER_0(rcsr_jrx, i32)
+
+#include "def-helper.h"
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
new file mode 100644
index 0000000..e84ba48
--- /dev/null
+++ b/target-lm32/op_helper.c
@@ -0,0 +1,106 @@
+#include <assert.h>
+#include "exec.h"
+#include "helper.h"
+#include "host-utils.h"
+
+#include "hw/lm32_pic.h"
+#include "hw/lm32_juart.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#define MMUSUFFIX _mmu
+#define SHIFT 0
+#include "softmmu_template.h"
+#define SHIFT 1
+#include "softmmu_template.h"
+#define SHIFT 2
+#include "softmmu_template.h"
+#define SHIFT 3
+#include "softmmu_template.h"
+
+void helper_raise_exception(uint32_t index)
+{
+    env->exception_index = index;
+    cpu_loop_exit();
+}
+
+void helper_hlt(void)
+{
+    env->halted = 1;
+    env->exception_index = EXCP_HLT;
+    cpu_loop_exit();
+}
+
+void helper_wcsr_im(uint32_t im)
+{
+    lm32_pic_set_im(env->pic_state, im);
+}
+
+void helper_wcsr_ip(uint32_t im)
+{
+    lm32_pic_set_ip(env->pic_state, im);
+}
+
+void helper_wcsr_jtx(uint32_t jtx)
+{
+    lm32_juart_set_jtx(env->juart_state, jtx);
+}
+
+void helper_wcsr_jrx(uint32_t jrx)
+{
+    lm32_juart_set_jrx(env->juart_state, jrx);
+}
+
+uint32_t helper_rcsr_im(void)
+{
+    return lm32_pic_get_im(env->pic_state);
+}
+
+uint32_t helper_rcsr_ip(void)
+{
+    return lm32_pic_get_ip(env->pic_state);
+}
+
+uint32_t helper_rcsr_jtx(void)
+{
+    return lm32_juart_get_jtx(env->juart_state);
+}
+
+uint32_t helper_rcsr_jrx(void)
+{
+    return lm32_juart_get_jrx(env->juart_state);
+}
+
+/* Try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
+{
+    TranslationBlock *tb;
+    CPUState *saved_env;
+    unsigned long pc;
+    int ret;
+
+    /* XXX: hack to restore env in all cases, even if not called from
+       generated code */
+    saved_env = env;
+    env = cpu_single_env;
+
+    ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    if (unlikely(ret)) {
+        if (retaddr) {
+            /* now we have a real cpu fault */
+            pc = (unsigned long)retaddr;
+            tb = tb_find_pc(pc);
+            if (tb) {
+                /* the PC is inside the translated code. It means that we have
+                   a virtual CPU fault */
+                cpu_restore_state(tb, env, pc, NULL);
+            }
+        }
+        cpu_loop_exit();
+    }
+    env = saved_env;
+}
+#endif
+
commit 17c0fa3d57ee1ee456a948b16b2905bf87833b8f
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:03 2011 +0100

    lm32: translation routines
    
    This patch adds the main translation routine. All opcodes of the
    LatticeMico32 processor are supported and translated to TCG ops.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-lm32/helper.c b/target-lm32/helper.c
new file mode 100644
index 0000000..318e2cf
--- /dev/null
+++ b/target-lm32/helper.c
@@ -0,0 +1,259 @@
+/*
+ *  LatticeMico32 helper routines.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "exec-all.h"
+#include "host-utils.h"
+
+int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+                               int mmu_idx, int is_softmmu)
+{
+    int prot;
+
+    address &= TARGET_PAGE_MASK;
+    prot = PAGE_BITS;
+    if (env->flags & LM32_FLAG_IGNORE_MSB) {
+        tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
+                TARGET_PAGE_SIZE);
+    } else {
+        tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
+    }
+
+    return 0;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+    return addr & TARGET_PAGE_MASK;
+}
+
+void do_interrupt(CPUState *env)
+{
+    qemu_log_mask(CPU_LOG_INT,
+            "exception at pc=%x type=%x\n", env->pc, env->exception_index);
+
+    switch (env->exception_index) {
+    case EXCP_INSN_BUS_ERROR:
+    case EXCP_DATA_BUS_ERROR:
+    case EXCP_DIVIDE_BY_ZERO:
+    case EXCP_IRQ:
+    case EXCP_SYSTEMCALL:
+        /* non-debug exceptions */
+        env->regs[R_EA] = env->pc;
+        env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
+        env->ie &= ~IE_IE;
+        if (env->dc & DC_RE) {
+            env->pc = env->deba + (env->exception_index * 32);
+        } else {
+            env->pc = env->eba + (env->exception_index * 32);
+        }
+        log_cpu_state_mask(CPU_LOG_INT, env, 0);
+        break;
+    case EXCP_BREAKPOINT:
+    case EXCP_WATCHPOINT:
+        /* debug exceptions */
+        env->regs[R_BA] = env->pc;
+        env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
+        env->ie &= ~IE_IE;
+        if (env->dc & DC_RE) {
+            env->pc = env->deba + (env->exception_index * 32);
+        } else {
+            env->pc = env->eba + (env->exception_index * 32);
+        }
+        log_cpu_state_mask(CPU_LOG_INT, env, 0);
+        break;
+    default:
+        cpu_abort(env, "unhandled exception type=%d\n",
+                  env->exception_index);
+        break;
+    }
+}
+
+typedef struct {
+    const char *name;
+    uint32_t revision;
+    uint8_t num_interrupts;
+    uint8_t num_breakpoints;
+    uint8_t num_watchpoints;
+    uint32_t features;
+} LM32Def;
+
+static const LM32Def lm32_defs[] = {
+    {
+        .name = "lm32-basic",
+        .revision = 3,
+        .num_interrupts = 32,
+        .num_breakpoints = 4,
+        .num_watchpoints = 4,
+        .features = (LM32_FEATURE_SHIFT
+                     | LM32_FEATURE_SIGN_EXTEND
+                     | LM32_FEATURE_CYCLE_COUNT),
+    },
+    {
+        .name = "lm32-standard",
+        .revision = 3,
+        .num_interrupts = 32,
+        .num_breakpoints = 4,
+        .num_watchpoints = 4,
+        .features = (LM32_FEATURE_MULTIPLY
+                     | LM32_FEATURE_DIVIDE
+                     | LM32_FEATURE_SHIFT
+                     | LM32_FEATURE_SIGN_EXTEND
+                     | LM32_FEATURE_I_CACHE
+                     | LM32_FEATURE_CYCLE_COUNT),
+    },
+    {
+        .name = "lm32-full",
+        .revision = 3,
+        .num_interrupts = 32,
+        .num_breakpoints = 4,
+        .num_watchpoints = 4,
+        .features = (LM32_FEATURE_MULTIPLY
+                     | LM32_FEATURE_DIVIDE
+                     | LM32_FEATURE_SHIFT
+                     | LM32_FEATURE_SIGN_EXTEND
+                     | LM32_FEATURE_I_CACHE
+                     | LM32_FEATURE_D_CACHE
+                     | LM32_FEATURE_CYCLE_COUNT),
+    }
+};
+
+void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    int i;
+
+    cpu_fprintf(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
+        cpu_fprintf(f, "  %s\n", lm32_defs[i].name);
+    }
+}
+
+static const LM32Def *cpu_lm32_find_by_name(const char *name)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
+        if (strcasecmp(name, lm32_defs[i].name) == 0) {
+            return &lm32_defs[i];
+        }
+    }
+
+    return NULL;
+}
+
+static uint32_t cfg_by_def(const LM32Def *def)
+{
+    uint32_t cfg = 0;
+
+    if (def->features & LM32_FEATURE_MULTIPLY) {
+        cfg |= CFG_M;
+    }
+
+    if (def->features & LM32_FEATURE_DIVIDE) {
+        cfg |= CFG_D;
+    }
+
+    if (def->features & LM32_FEATURE_SHIFT) {
+        cfg |= CFG_S;
+    }
+
+    if (def->features & LM32_FEATURE_SIGN_EXTEND) {
+        cfg |= CFG_X;
+    }
+
+    if (def->features & LM32_FEATURE_I_CACHE) {
+        cfg |= CFG_IC;
+    }
+
+    if (def->features & LM32_FEATURE_D_CACHE) {
+        cfg |= CFG_DC;
+    }
+
+    if (def->features & LM32_FEATURE_CYCLE_COUNT) {
+        cfg |= CFG_CC;
+    }
+
+    cfg |= (def->num_interrupts << CFG_INT_SHIFT);
+    cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
+    cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
+    cfg |= (def->revision << CFG_REV_SHIFT);
+
+    return cfg;
+}
+
+CPUState *cpu_lm32_init(const char *cpu_model)
+{
+    CPUState *env;
+    const LM32Def *def;
+    static int tcg_initialized;
+
+    def = cpu_lm32_find_by_name(cpu_model);
+    if (!def) {
+        return NULL;
+    }
+
+    env = qemu_mallocz(sizeof(CPUState));
+
+    env->features = def->features;
+    env->num_bps = def->num_breakpoints;
+    env->num_wps = def->num_watchpoints;
+    env->cfg = cfg_by_def(def);
+    env->flags = 0;
+
+    cpu_exec_init(env);
+    cpu_reset(env);
+
+    if (!tcg_initialized) {
+        tcg_initialized = 1;
+        lm32_translate_init();
+    }
+
+    return env;
+}
+
+/* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
+ * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
+ * 0x80000000-0xffffffff is not cached and used to access IO devices. */
+void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
+{
+    if (value) {
+        env->flags |= LM32_FLAG_IGNORE_MSB;
+    } else {
+        env->flags &= ~LM32_FLAG_IGNORE_MSB;
+    }
+}
+
+void cpu_reset(CPUState *env)
+{
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    tlb_flush(env, 1);
+
+    /* reset cpu state */
+    memset(env, 0, offsetof(CPULM32State, breakpoints));
+}
+
diff --git a/target-lm32/lm32-decode.h b/target-lm32/lm32-decode.h
new file mode 100644
index 0000000..f745b39
--- /dev/null
+++ b/target-lm32/lm32-decode.h
@@ -0,0 +1,78 @@
+/*
+ *  LatticeMico32 instruction decoding macros.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Convenient binary macros */
+#define HEX__(n) 0x##n##LU
+#define B8__(x) (((x&0x0000000FLU) ? 1 : 0) \
+                  + ((x&0x000000F0LU) ? 2 : 0) \
+                  + ((x&0x00000F00LU) ? 4 : 0) \
+                  + ((x&0x0000F000LU) ? 8 : 0) \
+                  + ((x&0x000F0000LU) ? 16 : 0) \
+                  + ((x&0x00F00000LU) ? 32 : 0) \
+                  + ((x&0x0F000000LU) ? 64 : 0) \
+                  + ((x&0xF0000000LU) ? 128 : 0))
+#define B8(d) ((unsigned char)B8__(HEX__(d)))
+
+/* Decode logic, value and mask.  */
+#define DEC_ADD     {B8(00001101), B8(00011111)}
+#define DEC_AND     {B8(00001000), B8(00011111)}
+#define DEC_ANDHI   {B8(00011000), B8(00111111)}
+#define DEC_B       {B8(00110000), B8(00111111)}
+#define DEC_BI      {B8(00111000), B8(00111111)}
+#define DEC_BE      {B8(00010001), B8(00111111)}
+#define DEC_BG      {B8(00010010), B8(00111111)}
+#define DEC_BGE     {B8(00010011), B8(00111111)}
+#define DEC_BGEU    {B8(00010100), B8(00111111)}
+#define DEC_BGU     {B8(00010101), B8(00111111)}
+#define DEC_BNE     {B8(00010111), B8(00111111)}
+#define DEC_CALL    {B8(00110110), B8(00111111)}
+#define DEC_CALLI   {B8(00111110), B8(00111111)}
+#define DEC_CMPE    {B8(00011001), B8(00011111)}
+#define DEC_CMPG    {B8(00011010), B8(00011111)}
+#define DEC_CMPGE   {B8(00011011), B8(00011111)}
+#define DEC_CMPGEU  {B8(00011100), B8(00011111)}
+#define DEC_CMPGU   {B8(00011101), B8(00011111)}
+#define DEC_CMPNE   {B8(00011111), B8(00011111)}
+#define DEC_DIVU    {B8(00100011), B8(00111111)}
+#define DEC_LB      {B8(00000100), B8(00111111)}
+#define DEC_LBU     {B8(00010000), B8(00111111)}
+#define DEC_LH      {B8(00000111), B8(00111111)}
+#define DEC_LHU     {B8(00001011), B8(00111111)}
+#define DEC_LW      {B8(00001010), B8(00111111)}
+#define DEC_MODU    {B8(00110001), B8(00111111)}
+#define DEC_MUL     {B8(00000010), B8(00011111)}
+#define DEC_NOR     {B8(00000001), B8(00011111)}
+#define DEC_OR      {B8(00001110), B8(00011111)}
+#define DEC_ORHI    {B8(00011110), B8(00111111)}
+#define DEC_RAISE   {B8(00101011), B8(00111111)}
+#define DEC_RCSR    {B8(00100100), B8(00111111)}
+#define DEC_SB      {B8(00001100), B8(00111111)}
+#define DEC_SEXTB   {B8(00101100), B8(00111111)}
+#define DEC_SEXTH   {B8(00110111), B8(00111111)}
+#define DEC_SH      {B8(00000011), B8(00111111)}
+#define DEC_SL      {B8(00001111), B8(00011111)}
+#define DEC_SR      {B8(00000101), B8(00011111)}
+#define DEC_SRU     {B8(00000000), B8(00011111)}
+#define DEC_SUB     {B8(00110010), B8(00111111)}
+#define DEC_SW      {B8(00010110), B8(00111111)}
+#define DEC_USER    {B8(00110011), B8(00111111)}
+#define DEC_WCSR    {B8(00110100), B8(00111111)}
+#define DEC_XNOR    {B8(00001001), B8(00011111)}
+#define DEC_XOR     {B8(00000110), B8(00011111)}
+
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
new file mode 100644
index 0000000..0b0e405
--- /dev/null
+++ b/target-lm32/translate.c
@@ -0,0 +1,1317 @@
+/*
+ *  LatticeMico32 main translation routines.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "helper.h"
+#include "tcg-op.h"
+#include "lm32-decode.h"
+#include "qemu-common.h"
+
+#include "hw/lm32_pic.h"
+
+#define GEN_HELPER 1
+#include "helper.h"
+
+#define DISAS_LM32 1
+#if DISAS_LM32
+#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
+#else
+#  define LOG_DIS(...) do { } while (0)
+#endif
+
+#define EXTRACT_FIELD(src, start, end) \
+            (((src) >> start) & ((1 << (end - start + 1)) - 1))
+
+#define MEM_INDEX 0
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_R[32];
+static TCGv cpu_pc;
+static TCGv cpu_ie;
+static TCGv cpu_icc;
+static TCGv cpu_dcc;
+static TCGv cpu_cc;
+static TCGv cpu_cfg;
+static TCGv cpu_eba;
+static TCGv cpu_dc;
+static TCGv cpu_deba;
+static TCGv cpu_bp[4];
+static TCGv cpu_wp[4];
+
+#include "gen-icount.h"
+
+enum {
+    OP_FMT_RI,
+    OP_FMT_RR,
+    OP_FMT_CR,
+    OP_FMT_I
+};
+
+/* This is the state at translation time.  */
+typedef struct DisasContext {
+    CPUState *env;
+    target_ulong pc;
+
+    /* Decoder.  */
+    int format;
+    uint32_t ir;
+    uint8_t opcode;
+    uint8_t r0, r1, r2, csr;
+    uint16_t imm5;
+    uint16_t imm16;
+    uint32_t imm26;
+
+    unsigned int delayed_branch;
+    unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
+    int is_jmp;
+
+    int nr_nops;
+    struct TranslationBlock *tb;
+    int singlestep_enabled;
+} DisasContext;
+
+static const char *regnames[] = {
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26/gp", "r27/fp", "r28/sp", "r29/ra",
+    "r30/ea", "r31/ba", "bp0", "bp1", "bp2", "bp3", "wp0",
+    "wp1", "wp2", "wp3"
+};
+
+static inline int zero_extend(unsigned int val, int width)
+{
+    return val & ((1 << width) - 1);
+}
+
+static inline int sign_extend(unsigned int val, int width)
+{
+    int sval;
+
+    /* LSL.  */
+    val <<= 32 - width;
+    sval = val;
+    /* ASR.  */
+    sval >>= 32 - width;
+
+    return sval;
+}
+
+static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
+{
+    TCGv_i32 tmp = tcg_const_i32(index);
+
+    gen_helper_raise_exception(tmp);
+    tcg_temp_free_i32(tmp);
+}
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+    TranslationBlock *tb;
+
+    tb = dc->tb;
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+            likely(!dc->singlestep_enabled)) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_tl(cpu_pc, dest);
+        tcg_gen_exit_tb((long)tb + n);
+    } else {
+        tcg_gen_movi_tl(cpu_pc, dest);
+        if (dc->singlestep_enabled) {
+            t_gen_raise_exception(dc, EXCP_DEBUG);
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static void dec_add(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        if (dc->r0 == R_R0) {
+            if (dc->r1 == R_R0 && dc->imm16 == 0) {
+                LOG_DIS("nop\n");
+            } else {
+                LOG_DIS("mvi r%d, %d\n", dc->r1, sign_extend(dc->imm16, 16));
+            }
+        } else {
+            LOG_DIS("addi r%d, r%d, %d\n", dc->r1, dc->r0,
+                    sign_extend(dc->imm16, 16));
+        }
+    } else {
+        LOG_DIS("add r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_addi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                sign_extend(dc->imm16, 16));
+    } else {
+        tcg_gen_add_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+static void dec_and(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0,
+                zero_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                zero_extend(dc->imm16, 16));
+    } else  {
+        if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) {
+            tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
+            gen_helper_hlt();
+        } else {
+            tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+        }
+    }
+}
+
+static void dec_andhi(DisasContext *dc)
+{
+    LOG_DIS("andhi r%d, r%d, %d\n", dc->r2, dc->r0, dc->imm16);
+
+    tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
+}
+
+static void dec_b(DisasContext *dc)
+{
+    if (dc->r0 == R_RA) {
+        LOG_DIS("ret\n");
+    } else if (dc->r0 == R_EA) {
+        LOG_DIS("eret\n");
+    } else if (dc->r0 == R_BA) {
+        LOG_DIS("bret\n");
+    } else {
+        LOG_DIS("b r%d\n", dc->r0);
+    }
+
+    /* restore IE.IE in case of an eret */
+    if (dc->r0 == R_EA) {
+        TCGv t0 = tcg_temp_new();
+        int l1 = gen_new_label();
+        tcg_gen_andi_tl(t0, cpu_ie, IE_EIE);
+        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1);
+        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
+        gen_set_label(l1);
+        tcg_temp_free(t0);
+    } else if (dc->r0 == R_BA) {
+        TCGv t0 = tcg_temp_new();
+        int l1 = gen_new_label();
+        tcg_gen_andi_tl(t0, cpu_ie, IE_BIE);
+        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1);
+        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
+        gen_set_label(l1);
+        tcg_temp_free(t0);
+    }
+    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+static void dec_bi(DisasContext *dc)
+{
+    LOG_DIS("bi %d\n", sign_extend(dc->imm26 << 2, 26));
+
+    gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+static inline void gen_cond_branch(DisasContext *dc, int cond)
+{
+    int l1;
+
+    l1 = gen_new_label();
+    tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1);
+    gen_goto_tb(dc, 0, dc->pc + 4);
+    gen_set_label(l1);
+    gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16)));
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+static void dec_be(DisasContext *dc)
+{
+    LOG_DIS("be r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16) * 4);
+
+    gen_cond_branch(dc, TCG_COND_EQ);
+}
+
+static void dec_bg(DisasContext *dc)
+{
+    LOG_DIS("bg r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16 * 4));
+
+    gen_cond_branch(dc, TCG_COND_GT);
+}
+
+static void dec_bge(DisasContext *dc)
+{
+    LOG_DIS("bge r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16) * 4);
+
+    gen_cond_branch(dc, TCG_COND_GE);
+}
+
+static void dec_bgeu(DisasContext *dc)
+{
+    LOG_DIS("bgeu r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16) * 4);
+
+    gen_cond_branch(dc, TCG_COND_GEU);
+}
+
+static void dec_bgu(DisasContext *dc)
+{
+    LOG_DIS("bgu r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16) * 4);
+
+    gen_cond_branch(dc, TCG_COND_GTU);
+}
+
+static void dec_bne(DisasContext *dc)
+{
+    LOG_DIS("bne r%d, r%d, %d\n", dc->r0, dc->r1,
+            sign_extend(dc->imm16, 16) * 4);
+
+    gen_cond_branch(dc, TCG_COND_NE);
+}
+
+static void dec_call(DisasContext *dc)
+{
+    LOG_DIS("call r%d\n", dc->r0);
+
+    tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
+    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
+
+    dc->is_jmp = DISAS_JUMP;
+}
+
+static void dec_calli(DisasContext *dc)
+{
+    LOG_DIS("calli %d\n", sign_extend(dc->imm26, 26) * 4);
+
+    tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
+    gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
+
+    dc->is_jmp = DISAS_TB_JUMP;
+}
+
+static inline void gen_compare(DisasContext *dc, int cond)
+{
+    int rX = (dc->format == OP_FMT_RR) ? dc->r2 : dc->r1;
+    int rY = (dc->format == OP_FMT_RR) ? dc->r0 : dc->r0;
+    int rZ = (dc->format == OP_FMT_RR) ? dc->r1 : -1;
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_setcondi_tl(cond, cpu_R[rX], cpu_R[rY],
+                sign_extend(dc->imm16, 16));
+    } else {
+        tcg_gen_setcond_tl(cond, cpu_R[rX], cpu_R[rY], cpu_R[rZ]);
+    }
+}
+
+static void dec_cmpe(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpei r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpe r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_EQ);
+}
+
+static void dec_cmpg(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpg r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_GT);
+}
+
+static void dec_cmpge(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpge r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_GE);
+}
+
+static void dec_cmpgeu(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_GEU);
+}
+
+static void dec_cmpgu(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_GTU);
+}
+
+static void dec_cmpne(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("cmpne r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    gen_compare(dc, TCG_COND_NE);
+}
+
+static void dec_divu(DisasContext *dc)
+{
+    int l1;
+
+    LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+
+    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
+        cpu_abort(dc->env, "hardware divider is not available\n");
+    }
+
+    l1 = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
+    tcg_gen_movi_tl(cpu_pc, dc->pc);
+    t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
+    gen_set_label(l1);
+    tcg_gen_divu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+}
+
+static void dec_lb(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("lb r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_ld8s(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_lbu(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("lbu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_ld8u(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_lh(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("lh r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_ld16s(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_lhu(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("lhu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_ld16u(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_lw(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("lw r%d, (r%d+%d)\n", dc->r1, dc->r0, sign_extend(dc->imm16, 16));
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_ld32s(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_modu(DisasContext *dc)
+{
+    int l1;
+
+    LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1);
+
+    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
+        cpu_abort(dc->env, "hardware divider is not available\n");
+    }
+
+    l1 = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
+    tcg_gen_movi_tl(cpu_pc, dc->pc);
+    t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
+    gen_set_label(l1);
+    tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+}
+
+static void dec_mul(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("muli r%d, r%d, %d\n", dc->r0, dc->r1,
+                sign_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (!(dc->env->features & LM32_FEATURE_MULTIPLY)) {
+        cpu_abort(dc->env, "hardware multiplier is not available\n");
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_muli_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                sign_extend(dc->imm16, 16));
+    } else {
+        tcg_gen_mul_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+static void dec_nor(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("nori r%d, r%d, %d\n", dc->r0, dc->r1,
+                zero_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("nor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_movi_tl(t0, zero_extend(dc->imm16, 16));
+        tcg_gen_nor_tl(cpu_R[dc->r1], cpu_R[dc->r0], t0);
+        tcg_temp_free(t0);
+    } else {
+        tcg_gen_nor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+static void dec_or(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("ori r%d, r%d, %d\n", dc->r1, dc->r0,
+                zero_extend(dc->imm16, 16));
+    } else {
+        if (dc->r1 == R_R0) {
+            LOG_DIS("mv r%d, r%d\n", dc->r2, dc->r0);
+        } else {
+            LOG_DIS("or r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+        }
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                zero_extend(dc->imm16, 16));
+    } else {
+        tcg_gen_or_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+static void dec_orhi(DisasContext *dc)
+{
+    if (dc->r0 == R_R0) {
+        LOG_DIS("mvhi r%d, %d\n", dc->r1, dc->imm16);
+    } else {
+        LOG_DIS("orhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16);
+    }
+
+    tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
+}
+
+static void dec_raise(DisasContext *dc)
+{
+    TCGv t0;
+    int l1;
+
+    if (dc->imm5 == 7) {
+        LOG_DIS("scall\n");
+    } else if (dc->imm5 == 2) {
+        LOG_DIS("break\n");
+    } else {
+        cpu_abort(dc->env, "invalid opcode\n");
+    }
+
+    t0 = tcg_temp_new();
+    l1 = gen_new_label();
+
+    /* save IE.IE */
+    tcg_gen_andi_tl(t0, cpu_ie, IE_IE);
+
+    /* IE.IE = 0 */
+    tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
+
+    if (dc->imm5 == 7) {
+        /* IE.EIE = IE.IE */
+        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_EIE);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
+        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_EIE);
+        gen_set_label(l1);
+
+        /* gpr[ea] = PC */
+        tcg_gen_movi_tl(cpu_R[R_EA], dc->pc);
+        tcg_temp_free(t0);
+
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
+    } else {
+        /* IE.BIE = IE.IE */
+        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_BIE);
+        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_IE, l1);
+        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_BIE);
+        gen_set_label(l1);
+
+        /* gpr[ba] = PC */
+        tcg_gen_movi_tl(cpu_R[R_BA], dc->pc);
+        tcg_temp_free(t0);
+
+        tcg_gen_movi_tl(cpu_pc, dc->pc);
+        t_gen_raise_exception(dc, EXCP_BREAKPOINT);
+    }
+}
+
+static void dec_rcsr(DisasContext *dc)
+{
+    LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr);
+
+    switch (dc->csr) {
+    case CSR_IE:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie);
+        break;
+    case CSR_IM:
+        gen_helper_rcsr_im(cpu_R[dc->r2]);
+        break;
+    case CSR_IP:
+        gen_helper_rcsr_ip(cpu_R[dc->r2]);
+        break;
+    case CSR_CC:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc);
+        break;
+    case CSR_CFG:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg);
+        break;
+    case CSR_EBA:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba);
+        break;
+    case CSR_DC:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc);
+        break;
+    case CSR_DEBA:
+        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba);
+        break;
+    case CSR_JTX:
+        gen_helper_rcsr_jtx(cpu_R[dc->r2]);
+        break;
+    case CSR_JRX:
+        gen_helper_rcsr_jrx(cpu_R[dc->r2]);
+        break;
+    case CSR_ICC:
+    case CSR_DCC:
+    case CSR_BP0:
+    case CSR_BP1:
+    case CSR_BP2:
+    case CSR_BP3:
+    case CSR_WP0:
+    case CSR_WP1:
+    case CSR_WP2:
+    case CSR_WP3:
+        cpu_abort(dc->env, "invalid read access csr=%x\n", dc->csr);
+        break;
+    default:
+        cpu_abort(dc->env, "read_csr: unknown csr=%x\n", dc->csr);
+        break;
+    }
+}
+
+static void dec_sb(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("sb (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_st8(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_sextb(DisasContext *dc)
+{
+    LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0);
+
+    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
+        cpu_abort(dc->env, "hardware sign extender is not available\n");
+    }
+
+    tcg_gen_ext8s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
+}
+
+static void dec_sexth(DisasContext *dc)
+{
+    LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0);
+
+    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
+        cpu_abort(dc->env, "hardware sign extender is not available\n");
+    }
+
+    tcg_gen_ext16s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
+}
+
+static void dec_sh(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("sh (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_st16(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_sl(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
+    } else {
+        LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
+        cpu_abort(dc->env, "hardware shifter is not available\n");
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
+    } else {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
+        tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
+        tcg_temp_free(t0);
+    }
+}
+
+static void dec_sr(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("sri r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
+    } else {
+        LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
+        if (dc->format == OP_FMT_RI) {
+            /* TODO: check r1 == 1 during runtime */
+        } else {
+            if (dc->imm5 != 1) {
+                cpu_abort(dc->env, "hardware shifter is not available\n");
+            }
+        }
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
+    } else {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
+        tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
+        tcg_temp_free(t0);
+    }
+}
+
+static void dec_sru(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
+    } else {
+        LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
+        if (dc->format == OP_FMT_RI) {
+            /* TODO: check r1 == 1 during runtime */
+        } else {
+            if (dc->imm5 != 1) {
+                cpu_abort(dc->env, "hardware shifter is not available\n");
+            }
+        }
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
+    } else {
+        TCGv t0 = tcg_temp_new();
+        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
+        tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
+        tcg_temp_free(t0);
+    }
+}
+
+static void dec_sub(DisasContext *dc)
+{
+    LOG_DIS("sub r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+
+    tcg_gen_sub_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+}
+
+static void dec_sw(DisasContext *dc)
+{
+    TCGv t0;
+
+    LOG_DIS("sw (r%d+%d), r%d\n", dc->r0, sign_extend(dc->imm16, 16), dc->r1);
+
+    t0 = tcg_temp_new();
+    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
+    tcg_gen_qemu_st32(cpu_R[dc->r1], t0, MEM_INDEX);
+    tcg_temp_free(t0);
+}
+
+static void dec_user(DisasContext *dc)
+{
+    LOG_DIS("user");
+
+    cpu_abort(dc->env, "user insn undefined\n");
+}
+
+static void dec_wcsr(DisasContext *dc)
+{
+    int no;
+
+    LOG_DIS("wcsr r%d, %d\n", dc->r1, dc->csr);
+
+    switch (dc->csr) {
+    case CSR_IE:
+        tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]);
+        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    case CSR_IM:
+        /* mark as an io operation because it could cause an interrupt */
+        if (use_icount) {
+            gen_io_start();
+        }
+        gen_helper_wcsr_im(cpu_R[dc->r1]);
+        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
+        if (use_icount) {
+            gen_io_end();
+        }
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    case CSR_IP:
+        /* mark as an io operation because it could cause an interrupt */
+        if (use_icount) {
+            gen_io_start();
+        }
+        gen_helper_wcsr_ip(cpu_R[dc->r1]);
+        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
+        if (use_icount) {
+            gen_io_end();
+        }
+        dc->is_jmp = DISAS_UPDATE;
+        break;
+    case CSR_ICC:
+        /* TODO */
+        break;
+    case CSR_DCC:
+        /* TODO */
+        break;
+    case CSR_EBA:
+        tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]);
+        break;
+    case CSR_DEBA:
+        tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]);
+        break;
+    case CSR_JTX:
+        gen_helper_wcsr_jtx(cpu_R[dc->r1]);
+        break;
+    case CSR_JRX:
+        gen_helper_wcsr_jrx(cpu_R[dc->r1]);
+        break;
+    case CSR_DC:
+        tcg_gen_mov_tl(cpu_dc, cpu_R[dc->r1]);
+        break;
+    case CSR_BP0:
+    case CSR_BP1:
+    case CSR_BP2:
+    case CSR_BP3:
+        no = dc->csr - CSR_BP0;
+        if (dc->env->num_bps <= no) {
+            cpu_abort(dc->env, "breakpoint #%i is not available\n", no);
+        }
+        tcg_gen_mov_tl(cpu_bp[no], cpu_R[dc->r1]);
+        break;
+    case CSR_WP0:
+    case CSR_WP1:
+    case CSR_WP2:
+    case CSR_WP3:
+        no = dc->csr - CSR_WP0;
+        if (dc->env->num_wps <= no) {
+            cpu_abort(dc->env, "watchpoint #%i is not available\n", no);
+        }
+        tcg_gen_mov_tl(cpu_wp[no], cpu_R[dc->r1]);
+        break;
+    case CSR_CC:
+    case CSR_CFG:
+        cpu_abort(dc->env, "invalid write access csr=%x\n", dc->csr);
+        break;
+    default:
+        cpu_abort(dc->env, "write_csr unknown csr=%x\n", dc->csr);
+        break;
+    }
+}
+
+static void dec_xnor(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("xnori r%d, r%d, %d\n", dc->r0, dc->r1,
+                zero_extend(dc->imm16, 16));
+    } else {
+        if (dc->r1 == R_R0) {
+            LOG_DIS("not r%d, r%d\n", dc->r2, dc->r0);
+        } else {
+            LOG_DIS("xnor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+        }
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                zero_extend(dc->imm16, 16));
+        tcg_gen_not_tl(cpu_R[dc->r1], cpu_R[dc->r1]);
+    } else {
+        tcg_gen_eqv_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+static void dec_xor(DisasContext *dc)
+{
+    if (dc->format == OP_FMT_RI) {
+        LOG_DIS("xori r%d, r%d, %d\n", dc->r0, dc->r1,
+                zero_extend(dc->imm16, 16));
+    } else {
+        LOG_DIS("xor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
+    }
+
+    if (dc->format == OP_FMT_RI) {
+        tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
+                zero_extend(dc->imm16, 16));
+    } else {
+        tcg_gen_xor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
+    }
+}
+
+typedef struct {
+    struct {
+        uint32_t bits;
+        uint32_t mask;
+    };
+    void (*dec)(DisasContext *dc);
+} DecoderInfo;
+
+static const DecoderInfo decinfo[] = {
+    {DEC_ADD, dec_add},
+    {DEC_AND, dec_and},
+    {DEC_ANDHI, dec_andhi},
+    {DEC_B, dec_b},
+    {DEC_BI, dec_bi},
+    {DEC_BE, dec_be},
+    {DEC_BG, dec_bg},
+    {DEC_BGE, dec_bge},
+    {DEC_BGEU, dec_bgeu},
+    {DEC_BGU, dec_bgu},
+    {DEC_BNE, dec_bne},
+    {DEC_CALL, dec_call},
+    {DEC_CALLI, dec_calli},
+    {DEC_CMPE, dec_cmpe},
+    {DEC_CMPG, dec_cmpg},
+    {DEC_CMPGE, dec_cmpge},
+    {DEC_CMPGEU, dec_cmpgeu},
+    {DEC_CMPGU, dec_cmpgu},
+    {DEC_CMPNE, dec_cmpne},
+    {DEC_DIVU, dec_divu},
+    {DEC_LB, dec_lb},
+    {DEC_LBU, dec_lbu},
+    {DEC_LH, dec_lh},
+    {DEC_LHU, dec_lhu},
+    {DEC_LW, dec_lw},
+    {DEC_MODU, dec_modu},
+    {DEC_MUL, dec_mul},
+    {DEC_NOR, dec_nor},
+    {DEC_OR, dec_or},
+    {DEC_ORHI, dec_orhi},
+    {DEC_RAISE, dec_raise},
+    {DEC_RCSR, dec_rcsr},
+    {DEC_SB, dec_sb},
+    {DEC_SEXTB, dec_sextb},
+    {DEC_SEXTH, dec_sexth},
+    {DEC_SH, dec_sh},
+    {DEC_SL, dec_sl},
+    {DEC_SR, dec_sr},
+    {DEC_SRU, dec_sru},
+    {DEC_SUB, dec_sub},
+    {DEC_SW, dec_sw},
+    {DEC_USER, dec_user},
+    {DEC_WCSR, dec_wcsr},
+    {DEC_XNOR, dec_xnor},
+    {DEC_XOR, dec_xor},
+};
+
+static inline void decode(DisasContext *dc)
+{
+    uint32_t ir;
+    int i;
+
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+        tcg_gen_debug_insn_start(dc->pc);
+    }
+
+    dc->ir = ir = ldl_code(dc->pc);
+    LOG_DIS("%8.8x\t", dc->ir);
+
+    /* try guessing 'empty' instruction memory, although it may be a valid
+     * instruction sequence (eg. srui r0, r0, 0) */
+    if (dc->ir) {
+        dc->nr_nops = 0;
+    } else {
+        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
+        dc->nr_nops++;
+        if (dc->nr_nops > 4) {
+            cpu_abort(dc->env, "fetching nop sequence\n");
+        }
+    }
+
+    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
+
+    dc->imm5 = EXTRACT_FIELD(ir, 0, 4);
+    dc->imm16 = EXTRACT_FIELD(ir, 0, 15);
+    dc->imm26 = EXTRACT_FIELD(ir, 0, 25);
+
+    dc->csr = EXTRACT_FIELD(ir, 21, 25);
+    dc->r0 = EXTRACT_FIELD(ir, 21, 25);
+    dc->r1 = EXTRACT_FIELD(ir, 16, 20);
+    dc->r2 = EXTRACT_FIELD(ir, 11, 15);
+
+    /* bit 31 seems to indicate insn type.  */
+    if (ir & (1 << 31)) {
+        dc->format = OP_FMT_RR;
+    } else {
+        dc->format = OP_FMT_RI;
+    }
+
+    /* Large switch for all insns.  */
+    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
+        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
+            decinfo[i].dec(dc);
+            return;
+        }
+    }
+
+    cpu_abort(dc->env, "unknown opcode 0x%02x\n", dc->opcode);
+}
+
+static void check_breakpoint(CPUState *env, DisasContext *dc)
+{
+    CPUBreakpoint *bp;
+
+    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+            if (bp->pc == dc->pc) {
+                tcg_gen_movi_tl(cpu_pc, dc->pc);
+                t_gen_raise_exception(dc, EXCP_DEBUG);
+                dc->is_jmp = DISAS_UPDATE;
+             }
+        }
+    }
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+static void gen_intermediate_code_internal(CPUState *env,
+        TranslationBlock *tb, int search_pc)
+{
+    struct DisasContext ctx, *dc = &ctx;
+    uint16_t *gen_opc_end;
+    uint32_t pc_start;
+    int j, lj;
+    uint32_t next_page_start;
+    int num_insns;
+    int max_insns;
+
+    qemu_log_try_set_file(stderr);
+
+    pc_start = tb->pc;
+    dc->env = env;
+    dc->tb = tb;
+
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+    dc->is_jmp = DISAS_NEXT;
+    dc->pc = pc_start;
+    dc->singlestep_enabled = env->singlestep_enabled;
+    dc->nr_nops = 0;
+
+    if (pc_start & 3) {
+        cpu_abort(env, "LM32: unaligned PC=%x\n", pc_start);
+    }
+
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("-----------------------------------------\n");
+        log_cpu_state(env, 0);
+    }
+
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    lj = -1;
+    num_insns = 0;
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+
+    gen_icount_start();
+    do {
+        check_breakpoint(env, dc);
+
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            gen_opc_pc[lj] = dc->pc;
+            gen_opc_instr_start[lj] = 1;
+            gen_opc_icount[lj] = num_insns;
+        }
+
+        /* Pretty disas.  */
+        LOG_DIS("%8.8x:\t", dc->pc);
+
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        decode(dc);
+        dc->pc += 4;
+        num_insns++;
+
+    } while (!dc->is_jmp
+         && gen_opc_ptr < gen_opc_end
+         && !env->singlestep_enabled
+         && !singlestep
+         && (dc->pc < next_page_start)
+         && num_insns < max_insns);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+    if (unlikely(env->singlestep_enabled)) {
+        if (dc->is_jmp == DISAS_NEXT) {
+            tcg_gen_movi_tl(cpu_pc, dc->pc);
+        }
+        t_gen_raise_exception(dc, EXCP_DEBUG);
+    } else {
+        switch (dc->is_jmp) {
+        case DISAS_NEXT:
+            gen_goto_tb(dc, 1, dc->pc);
+            break;
+        default:
+        case DISAS_JUMP:
+        case DISAS_UPDATE:
+            /* indicate that the hash table must be used
+               to find the next TB */
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_TB_JUMP:
+            /* nothing more to generate */
+            break;
+        }
+    }
+
+    gen_icount_end(tb, num_insns);
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j) {
+            gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+        qemu_log("\n");
+        log_target_disas(pc_start, dc->pc - pc_start, 0);
+        qemu_log("\nisize=%d osize=%zd\n",
+            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+    }
+#endif
+}
+
+void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(env, tb, 1);
+}
+
+void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+                     int flags)
+{
+    int i;
+
+    if (!env || !f) {
+        return;
+    }
+
+    cpu_fprintf(f, "IN: PC=%x %s\n",
+                env->pc, lookup_symbol(env->pc));
+
+    cpu_fprintf(f, "ie=%8.8x (IE=%x EIE=%x BIE=%x) im=%8.8x ip=%8.8x\n",
+             env->ie,
+             (env->ie & IE_IE) ? 1 : 0,
+             (env->ie & IE_EIE) ? 1 : 0,
+             (env->ie & IE_BIE) ? 1 : 0,
+             lm32_pic_get_im(env->pic_state),
+             lm32_pic_get_ip(env->pic_state));
+    cpu_fprintf(f, "eba=%8.8x deba=%8.8x\n",
+             env->eba,
+             env->deba);
+
+    for (i = 0; i < 32; i++) {
+        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
+        if ((i + 1) % 4 == 0) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\n\n");
+}
+
+void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
+                 unsigned long searched_pc, int pc_pos, void *puc)
+{
+    env->pc = gen_opc_pc[pc_pos];
+}
+
+void lm32_translate_init(void)
+{
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
+        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+                          offsetof(CPUState, regs[i]),
+                          regnames[i]);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) {
+        cpu_bp[i] = tcg_global_mem_new(TCG_AREG0,
+                          offsetof(CPUState, bp[i]),
+                          regnames[32+i]);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) {
+        cpu_wp[i] = tcg_global_mem_new(TCG_AREG0,
+                          offsetof(CPUState, wp[i]),
+                          regnames[36+i]);
+    }
+
+    cpu_pc = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, pc),
+                    "pc");
+    cpu_ie = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, ie),
+                    "ie");
+    cpu_icc = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, icc),
+                    "icc");
+    cpu_dcc = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, dcc),
+                    "dcc");
+    cpu_cc = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, cc),
+                    "cc");
+    cpu_cfg = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, cfg),
+                    "cfg");
+    cpu_eba = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, eba),
+                    "eba");
+    cpu_dc = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, dc),
+                    "dc");
+    cpu_deba = tcg_global_mem_new(TCG_AREG0,
+                    offsetof(CPUState, deba),
+                    "deba");
+}
+
commit 81ea0e130470bb307e5ab7e2d71e7b80b46ef1bf
Author: Michael Walle <michael at walle.cc>
Date:   Thu Feb 17 23:45:02 2011 +0100

    LatticeMico32 target support
    
    This patch adds support for the LatticeMico32 softcore processor by Lattice
    Semiconductor.
    
    Signed-off-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 220589e..857976a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -247,6 +247,8 @@ obj-ppc-y += xilinx_timer.o
 obj-ppc-y += xilinx_uartlite.o
 obj-ppc-y += xilinx_ethlite.o
 
+# LM32 peripherals
+
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
 obj-mips-y += vga.o i8259.o
diff --git a/arch_init.c b/arch_init.c
index cc56f0f..0c09f91 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -64,6 +64,8 @@ const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".con
 #define QEMU_ARCH QEMU_ARCH_I386
 #elif defined(TARGET_M68K)
 #define QEMU_ARCH QEMU_ARCH_M68K
+#elif defined(TARGET_LM32)
+#define QEMU_ARCH QEMU_ARCH_LM32
 #elif defined(TARGET_MICROBLAZE)
 #define QEMU_ARCH QEMU_ARCH_MICROBLAZE
 #elif defined(TARGET_MIPS)
diff --git a/arch_init.h b/arch_init.h
index 17c9164..c83360c 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -10,12 +10,13 @@ enum {
     QEMU_ARCH_CRIS = 4,
     QEMU_ARCH_I386 = 8,
     QEMU_ARCH_M68K = 16,
-    QEMU_ARCH_MICROBLAZE = 32,
-    QEMU_ARCH_MIPS = 64,
-    QEMU_ARCH_PPC = 128,
-    QEMU_ARCH_S390X = 256,
-    QEMU_ARCH_SH4 = 512,
-    QEMU_ARCH_SPARC = 1024,
+    QEMU_ARCH_LM32 = 32,
+    QEMU_ARCH_MICROBLAZE = 64,
+    QEMU_ARCH_MIPS = 128,
+    QEMU_ARCH_PPC = 256,
+    QEMU_ARCH_S390X = 512,
+    QEMU_ARCH_SH4 = 1024,
+    QEMU_ARCH_SPARC = 2048,
 };
 
 extern const uint32_t arch_type;
diff --git a/cpu-exec.c b/cpu-exec.c
index b03b3a7..70c3e5a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -239,6 +239,7 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_ALPHA)
 #elif defined(TARGET_ARM)
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
@@ -292,6 +293,8 @@ int cpu_exec(CPUState *env1)
                     env->old_exception = -1;
 #elif defined(TARGET_PPC)
                     do_interrupt(env);
+#elif defined(TARGET_LM32)
+                    do_interrupt(env);
 #elif defined(TARGET_MICROBLAZE)
                     do_interrupt(env);
 #elif defined(TARGET_MIPS)
@@ -332,7 +335,7 @@ int cpu_exec(CPUState *env1)
                     }
 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
-    defined(TARGET_MICROBLAZE)
+    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         env->halted = 1;
@@ -412,6 +415,13 @@ int cpu_exec(CPUState *env1)
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                         next_tb = 0;
                     }
+#elif defined(TARGET_LM32)
+                    if ((interrupt_request & CPU_INTERRUPT_HARD)
+                        && (env->ie & IE_IE)) {
+                        env->exception_index = EXCP_IRQ;
+                        do_interrupt(env);
+                        next_tb = 0;
+                    }
 #elif defined(TARGET_MICROBLAZE)
                     if ((interrupt_request & CPU_INTERRUPT_HARD)
                         && (env->sregs[SR_MSR] & MSR_IE)
@@ -624,6 +634,7 @@ int cpu_exec(CPUState *env1)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_LM32)
 #elif defined(TARGET_M68K)
     cpu_m68k_flush_flags(env, env->cc_op);
     env->cc_op = CC_OP_FLAGS;
diff --git a/elf.h b/elf.h
index d2f24f4..523c972 100644
--- a/elf.h
+++ b/elf.h
@@ -104,6 +104,7 @@ typedef int64_t  Elf64_Sxword;
 
 #define EM_H8_300H      47      /* Hitachi H8/300H */
 #define EM_H8S          48      /* Hitachi H8S     */
+#define EM_LATTICEMICO32 138    /* LatticeMico32 */
 
 /*
  * This is an interim value that we will use until the committee comes
diff --git a/poison.h b/poison.h
index d7db7f4..93c75fa 100644
--- a/poison.h
+++ b/poison.h
@@ -10,6 +10,7 @@
 #pragma GCC poison TARGET_ALPHA
 #pragma GCC poison TARGET_ARM
 #pragma GCC poison TARGET_CRIS
+#pragma GCC poison TARGET_LM32
 #pragma GCC poison TARGET_M68K
 #pragma GCC poison TARGET_MIPS
 #pragma GCC poison TARGET_MIPS64
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
new file mode 100644
index 0000000..8e2d26b
--- /dev/null
+++ b/target-lm32/cpu.h
@@ -0,0 +1,244 @@
+/*
+ *  LatticeMico32 virtual CPU header.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CPU_LM32_H
+#define CPU_LM32_H
+
+#define TARGET_LONG_BITS 32
+
+#define CPUState struct CPULM32State
+
+#include "qemu-common.h"
+#include "cpu-defs.h"
+struct CPULM32State;
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE EM_LATTICEMICO32
+
+#define NB_MMU_MODES 1
+#define TARGET_PAGE_BITS 12
+static inline int cpu_mmu_index(CPUState *env)
+{
+    return 0;
+}
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Exceptions indices */
+enum {
+    EXCP_RESET = 0,
+    EXCP_BREAKPOINT,
+    EXCP_INSN_BUS_ERROR,
+    EXCP_WATCHPOINT,
+    EXCP_DATA_BUS_ERROR,
+    EXCP_DIVIDE_BY_ZERO,
+    EXCP_IRQ,
+    EXCP_SYSTEMCALL
+};
+
+/* Registers */
+enum {
+    R_R0 = 0, R_R1, R_R2, R_R3, R_R4, R_R5, R_R6, R_R7, R_R8, R_R9, R_R10,
+    R_R11, R_R12, R_R13, R_R14, R_R15, R_R16, R_R17, R_R18, R_R19, R_R20,
+    R_R21, R_R22, R_R23, R_R24, R_R25, R_R26, R_R27, R_R28, R_R29, R_R30,
+    R_R31
+};
+
+/* Register aliases */
+enum {
+    R_GP = R_R26,
+    R_FP = R_R27,
+    R_SP = R_R28,
+    R_RA = R_R29,
+    R_EA = R_R30,
+    R_BA = R_R31
+};
+
+/* IE flags */
+enum {
+    IE_IE  = (1<<0),
+    IE_EIE = (1<<1),
+    IE_BIE = (1<<2),
+};
+
+/* DC flags */
+enum {
+    DC_SS  = (1<<0),
+    DC_RE  = (1<<1),
+    DC_C0  = (1<<2),
+    DC_C1  = (1<<3),
+    DC_C2  = (1<<4),
+    DC_C3  = (1<<5),
+};
+
+/* CFG mask */
+enum {
+    CFG_M         = (1<<0),
+    CFG_D         = (1<<1),
+    CFG_S         = (1<<2),
+    CFG_U         = (1<<3),
+    CFG_X         = (1<<4),
+    CFG_CC        = (1<<5),
+    CFG_IC        = (1<<6),
+    CFG_DC        = (1<<7),
+    CFG_G         = (1<<8),
+    CFG_H         = (1<<9),
+    CFG_R         = (1<<10),
+    CFG_J         = (1<<11),
+    CFG_INT_SHIFT = 12,
+    CFG_BP_SHIFT  = 18,
+    CFG_WP_SHIFT  = 22,
+    CFG_REV_SHIFT = 26,
+};
+
+/* CSRs */
+enum {
+    CSR_IE   = 0x00,
+    CSR_IM   = 0x01,
+    CSR_IP   = 0x02,
+    CSR_ICC  = 0x03,
+    CSR_DCC  = 0x04,
+    CSR_CC   = 0x05,
+    CSR_CFG  = 0x06,
+    CSR_EBA  = 0x07,
+    CSR_DC   = 0x08,
+    CSR_DEBA = 0x09,
+    CSR_JTX  = 0x0e,
+    CSR_JRX  = 0x0f,
+    CSR_BP0  = 0x10,
+    CSR_BP1  = 0x11,
+    CSR_BP2  = 0x12,
+    CSR_BP3  = 0x13,
+    CSR_WP0  = 0x18,
+    CSR_WP1  = 0x19,
+    CSR_WP2  = 0x1a,
+    CSR_WP3  = 0x1b,
+};
+
+enum {
+    LM32_FEATURE_MULTIPLY     =  1,
+    LM32_FEATURE_DIVIDE       =  2,
+    LM32_FEATURE_SHIFT        =  4,
+    LM32_FEATURE_SIGN_EXTEND  =  8,
+    LM32_FEATURE_I_CACHE      = 16,
+    LM32_FEATURE_D_CACHE      = 32,
+    LM32_FEATURE_CYCLE_COUNT  = 64,
+};
+
+enum {
+    LM32_FLAG_IGNORE_MSB = 1,
+};
+
+typedef struct CPULM32State {
+    /* general registers */
+    uint32_t regs[32];
+
+    /* special registers */
+    uint32_t pc;        /* program counter */
+    uint32_t ie;        /* interrupt enable */
+    uint32_t icc;       /* instruction cache control */
+    uint32_t dcc;       /* data cache control */
+    uint32_t cc;        /* cycle counter */
+    uint32_t cfg;       /* configuration */
+
+    /* debug registers */
+    uint32_t dc;        /* debug control */
+    uint32_t bp[4];     /* breakpoint addresses */
+    uint32_t wp[4];     /* watchpoint addresses */
+
+    CPU_COMMON
+
+    uint32_t eba;       /* exception base address */
+    uint32_t deba;      /* debug exception base address */
+
+    /* interrupt controller handle for callbacks */
+    DeviceState *pic_state;
+    /* JTAG UART handle for callbacks */
+    DeviceState *juart_state;
+
+    /* processor core features */
+    uint32_t features;
+    uint32_t flags;
+    uint8_t num_bps;
+    uint8_t num_wps;
+
+} CPULM32State;
+
+
+CPUState *cpu_lm32_init(const char *cpu_model);
+void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_lm32_exec(CPUState *s);
+void cpu_lm32_close(CPUState *s);
+void do_interrupt(CPUState *env);
+/* you can call this signal handler from your SIGBUS and SIGSEGV
+   signal handlers to inform the virtual CPU of exceptions. non zero
+   is returned if the signal was handled by the virtual CPU.  */
+int cpu_lm32_signal_handler(int host_signum, void *pinfo,
+                          void *puc);
+void lm32_translate_init(void);
+void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value);
+
+#define cpu_list cpu_lm32_list
+#define cpu_init cpu_lm32_init
+#define cpu_exec cpu_lm32_exec
+#define cpu_gen_code cpu_lm32_gen_code
+#define cpu_signal_handler cpu_lm32_signal_handler
+
+#define CPU_SAVE_VERSION 1
+
+int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
+                            int mmu_idx, int is_softmmu);
+#define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault
+
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[R_SP] = newsp;
+    }
+    env->regs[R_R1] = 0;
+}
+#endif
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+}
+
+static inline int cpu_interrupts_enabled(CPUState *env)
+{
+    return env->ie & IE_IE;
+}
+
+#include "cpu-all.h"
+
+static inline target_ulong cpu_get_pc(CPUState *env)
+{
+    return env->pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = 0;
+}
+#endif
diff --git a/target-lm32/exec.h b/target-lm32/exec.h
new file mode 100644
index 0000000..348b723
--- /dev/null
+++ b/target-lm32/exec.h
@@ -0,0 +1,50 @@
+/*
+ *  LatticeMico32 execution defines.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael at walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dyngen-exec.h"
+
+register struct CPULM32State *env asm(AREG0);
+
+#include "cpu.h"
+#include "exec-all.h"
+
+static inline int cpu_has_work(CPUState *env)
+{
+    return env->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+static inline int cpu_halted(CPUState *env)
+{
+    if (!env->halted) {
+        return 0;
+    }
+
+    /* IRQ execeptions wakes us up.  */
+    if (cpu_has_work(env)) {
+        env->halted = 0;
+        return 0;
+    }
+    return EXCP_HALTED;
+}
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
commit ca27c052d992da83ce0786d81f85b87cd1f5d301
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 22 18:19:43 2011 +0000

    target-arm: Implement a minimal set of cp14 debug registers
    
    Newer ARM kernels try to probe for whether the CPU has hardware breakpoint
    support. For this to work QEMU has to implement a minimal set of the cp14
    debug registers. The architecture requires v7 cores to implement debug
    and so there is no defined way to report its absence; however in practice
    returning a zero DBGDIDR (ie with a reserved value for "debug architecture
    version") should cause well-written hw debug users to do the right thing.
    We also implement DBGDRAR and DBGDSAR as RAZ, indicating no memory mapped
    debug components.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 91203c2..062de5e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5778,6 +5778,34 @@ static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
     int rt = (insn >> 12) & 0xf;
     TCGv tmp;
 
+    /* Minimal set of debug registers, since we don't support debug */
+    if (op1 == 0 && crn == 0 && op2 == 0) {
+        switch (crm) {
+        case 0:
+            /* DBGDIDR: just RAZ. In particular this means the
+             * "debug architecture version" bits will read as
+             * a reserved value, which should cause Linux to
+             * not try to use the debug hardware.
+             */
+            tmp = tcg_const_i32(0);
+            store_reg(s, rt, tmp);
+            return 0;
+        case 1:
+        case 2:
+            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
+             * don't implement memory mapped debug components
+             */
+            if (ENABLE_ARCH_7) {
+                tmp = tcg_const_i32(0);
+                store_reg(s, rt, tmp);
+                return 0;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
     if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
         if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
             /* TEECR */
commit 3849902cd852d7de0783abc41cb0c57949d567fd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Mar 6 21:39:55 2011 +0000

    target-arm: Use TCG temporary leak debugging facilities
    
    Use the new TCG temporary leak debugging facilities to
    check that each ARM instruction does not leak temporaries.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index e01c8cd..91203c2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9149,6 +9149,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 
     gen_icount_start();
 
+    tcg_clear_temp_count();
+
     /* A note on handling of the condexec (IT) bits:
      *
      * We want to avoid the overhead of having to write the updated condexec
@@ -9258,6 +9260,11 @@ static inline void gen_intermediate_code_internal(CPUState *env,
             gen_set_label(dc->condlabel);
             dc->condjmp = 0;
         }
+
+        if (tcg_check_temp_count()) {
+            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
+        }
+
         /* Translation stops when a conditional branch is encountered.
          * Otherwise the subsequent code could get translated several times.
          * Also stop translation when a page boundary is reached.  This
commit 7d1b0095bff7157e856d1d0e6c4295641ced2752
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Mar 6 21:39:54 2011 +0000

    target-arm: Remove ad-hoc leak checking code
    
    This commit removes the ad-hoc resource leak checking code from
    target-arm. This includes replacing all uses of new_tmp() with
    tcg_temp_new_i32() and all uses of dead_tmp() with
    tcg_temp_free_i32().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index b08b636..e01c8cd 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -128,25 +128,9 @@ void arm_translate_init(void)
 #include "helpers.h"
 }
 
-static int num_temps;
-
-/* Allocate a temporary variable.  */
-static TCGv_i32 new_tmp(void)
-{
-    num_temps++;
-    return tcg_temp_new_i32();
-}
-
-/* Release a temporary variable.  */
-static void dead_tmp(TCGv tmp)
-{
-    tcg_temp_free(tmp);
-    num_temps--;
-}
-
 static inline TCGv load_cpu_offset(int offset)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_ld_i32(tmp, cpu_env, offset);
     return tmp;
 }
@@ -156,7 +140,7 @@ static inline TCGv load_cpu_offset(int offset)
 static inline void store_cpu_offset(TCGv var, int offset)
 {
     tcg_gen_st_i32(var, cpu_env, offset);
-    dead_tmp(var);
+    tcg_temp_free_i32(var);
 }
 
 #define store_cpu_field(var, name) \
@@ -181,7 +165,7 @@ static void load_reg_var(DisasContext *s, TCGv var, int reg)
 /* Create a new temporary and set it to the value of a CPU register.  */
 static inline TCGv load_reg(DisasContext *s, int reg)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     load_reg_var(s, tmp, reg);
     return tmp;
 }
@@ -195,7 +179,7 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
         s->is_jmp = DISAS_JUMP;
     }
     tcg_gen_mov_i32(cpu_R[reg], var);
-    dead_tmp(var);
+    tcg_temp_free_i32(var);
 }
 
 /* Value extensions.  */
@@ -219,37 +203,37 @@ static inline void gen_set_cpsr(TCGv var, uint32_t mask)
 
 static void gen_exception(int excp)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_movi_i32(tmp, excp);
     gen_helper_exception(tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 static void gen_smul_dual(TCGv a, TCGv b)
 {
-    TCGv tmp1 = new_tmp();
-    TCGv tmp2 = new_tmp();
+    TCGv tmp1 = tcg_temp_new_i32();
+    TCGv tmp2 = tcg_temp_new_i32();
     tcg_gen_ext16s_i32(tmp1, a);
     tcg_gen_ext16s_i32(tmp2, b);
     tcg_gen_mul_i32(tmp1, tmp1, tmp2);
-    dead_tmp(tmp2);
+    tcg_temp_free_i32(tmp2);
     tcg_gen_sari_i32(a, a, 16);
     tcg_gen_sari_i32(b, b, 16);
     tcg_gen_mul_i32(b, b, a);
     tcg_gen_mov_i32(a, tmp1);
-    dead_tmp(tmp1);
+    tcg_temp_free_i32(tmp1);
 }
 
 /* Byteswap each halfword.  */
 static void gen_rev16(TCGv var)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_shri_i32(tmp, var, 8);
     tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
     tcg_gen_shli_i32(var, var, 8);
     tcg_gen_andi_i32(var, var, 0xff00ff00);
     tcg_gen_or_i32(var, var, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Byteswap low halfword and sign extend.  */
@@ -298,7 +282,7 @@ static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
     TCGv_i64 tmp64 = tcg_temp_new_i64();
 
     tcg_gen_extu_i32_i64(tmp64, b);
-    dead_tmp(b);
+    tcg_temp_free_i32(b);
     tcg_gen_shli_i64(tmp64, tmp64, 32);
     tcg_gen_add_i64(a, tmp64, a);
 
@@ -312,7 +296,7 @@ static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
     TCGv_i64 tmp64 = tcg_temp_new_i64();
 
     tcg_gen_extu_i32_i64(tmp64, b);
-    dead_tmp(b);
+    tcg_temp_free_i32(b);
     tcg_gen_shli_i64(tmp64, tmp64, 32);
     tcg_gen_sub_i64(a, tmp64, a);
 
@@ -329,9 +313,9 @@ static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
     TCGv_i64 tmp2 = tcg_temp_new_i64();
 
     tcg_gen_extu_i32_i64(tmp1, a);
-    dead_tmp(a);
+    tcg_temp_free_i32(a);
     tcg_gen_extu_i32_i64(tmp2, b);
-    dead_tmp(b);
+    tcg_temp_free_i32(b);
     tcg_gen_mul_i64(tmp1, tmp1, tmp2);
     tcg_temp_free_i64(tmp2);
     return tmp1;
@@ -343,9 +327,9 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
     TCGv_i64 tmp2 = tcg_temp_new_i64();
 
     tcg_gen_ext_i32_i64(tmp1, a);
-    dead_tmp(a);
+    tcg_temp_free_i32(a);
     tcg_gen_ext_i32_i64(tmp2, b);
-    dead_tmp(b);
+    tcg_temp_free_i32(b);
     tcg_gen_mul_i64(tmp1, tmp1, tmp2);
     tcg_temp_free_i64(tmp2);
     return tmp1;
@@ -354,11 +338,11 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
 /* Swap low and high halfwords.  */
 static void gen_swap_half(TCGv var)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_shri_i32(tmp, var, 16);
     tcg_gen_shli_i32(var, var, 16);
     tcg_gen_or_i32(var, var, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
@@ -370,15 +354,15 @@ static void gen_swap_half(TCGv var)
 
 static void gen_add16(TCGv t0, TCGv t1)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_xor_i32(tmp, t0, t1);
     tcg_gen_andi_i32(tmp, tmp, 0x8000);
     tcg_gen_andi_i32(t0, t0, ~0x8000);
     tcg_gen_andi_i32(t1, t1, ~0x8000);
     tcg_gen_add_i32(t0, t0, t1);
     tcg_gen_xor_i32(t0, t0, tmp);
-    dead_tmp(tmp);
-    dead_tmp(t1);
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(t1);
 }
 
 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
@@ -386,10 +370,10 @@ static void gen_add16(TCGv t0, TCGv t1)
 /* Set CF to the top bit of var.  */
 static void gen_set_CF_bit31(TCGv var)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_shri_i32(tmp, var, 31);
     gen_set_CF(tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Set N and Z flags from var.  */
@@ -406,7 +390,7 @@ static void gen_adc(TCGv t0, TCGv t1)
     tcg_gen_add_i32(t0, t0, t1);
     tmp = load_cpu_field(CF);
     tcg_gen_add_i32(t0, t0, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* dest = T0 + T1 + CF. */
@@ -416,7 +400,7 @@ static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
     tcg_gen_add_i32(dest, t0, t1);
     tmp = load_cpu_field(CF);
     tcg_gen_add_i32(dest, dest, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* dest = T0 - T1 + CF - 1.  */
@@ -427,7 +411,7 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
     tmp = load_cpu_field(CF);
     tcg_gen_add_i32(dest, dest, tmp);
     tcg_gen_subi_i32(dest, dest, 1);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* FIXME:  Implement this natively.  */
@@ -435,7 +419,7 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
 
 static void shifter_out_im(TCGv var, int shift)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     if (shift == 0) {
         tcg_gen_andi_i32(tmp, var, 1);
     } else {
@@ -444,7 +428,7 @@ static void shifter_out_im(TCGv var, int shift)
             tcg_gen_andi_i32(tmp, tmp, 1);
     }
     gen_set_CF(tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Shift by immediate.  Includes special handling for shift == 0.  */
@@ -492,7 +476,7 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
             tcg_gen_shri_i32(var, var, 1);
             tcg_gen_shli_i32(tmp, tmp, 31);
             tcg_gen_or_i32(var, var, tmp);
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
         }
     }
 };
@@ -516,7 +500,7 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop,
                 tcg_gen_rotr_i32(var, var, shift); break;
         }
     }
-    dead_tmp(shift);
+    tcg_temp_free_i32(shift);
 }
 
 #define PAS_OP(pfx) \
@@ -655,7 +639,7 @@ static void gen_test_cc(int cc, int label)
         inv = gen_new_label();
         tmp = load_cpu_field(CF);
         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         tmp = load_cpu_field(ZF);
         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
         gen_set_label(inv);
@@ -663,7 +647,7 @@ static void gen_test_cc(int cc, int label)
     case 9: /* ls: !C || Z */
         tmp = load_cpu_field(CF);
         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         tmp = load_cpu_field(ZF);
         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
         break;
@@ -671,43 +655,43 @@ static void gen_test_cc(int cc, int label)
         tmp = load_cpu_field(VF);
         tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
         break;
     case 11: /* lt: N != V -> N ^ V != 0 */
         tmp = load_cpu_field(VF);
         tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
         break;
     case 12: /* gt: !Z && N == V */
         inv = gen_new_label();
         tmp = load_cpu_field(ZF);
         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         tmp = load_cpu_field(VF);
         tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
         gen_set_label(inv);
         break;
     case 13: /* le: Z || N != V */
         tmp = load_cpu_field(ZF);
         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         tmp = load_cpu_field(VF);
         tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
         break;
     default:
         fprintf(stderr, "Bad condition code 0x%x\n", cc);
         abort();
     }
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 static const uint8_t table_logic_cc[16] = {
@@ -736,10 +720,10 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 
     s->is_jmp = DISAS_UPDATE;
     if (s->thumb != (addr & 1)) {
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, addr & 1);
         tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
     }
     tcg_gen_movi_i32(cpu_R[15], addr & ~1);
 }
@@ -768,31 +752,31 @@ static inline void store_reg_bx(CPUState *env, DisasContext *s,
 
 static inline TCGv gen_ld8s(TCGv addr, int index)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_qemu_ld8s(tmp, addr, index);
     return tmp;
 }
 static inline TCGv gen_ld8u(TCGv addr, int index)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_qemu_ld8u(tmp, addr, index);
     return tmp;
 }
 static inline TCGv gen_ld16s(TCGv addr, int index)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_qemu_ld16s(tmp, addr, index);
     return tmp;
 }
 static inline TCGv gen_ld16u(TCGv addr, int index)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_qemu_ld16u(tmp, addr, index);
     return tmp;
 }
 static inline TCGv gen_ld32(TCGv addr, int index)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_qemu_ld32u(tmp, addr, index);
     return tmp;
 }
@@ -805,17 +789,17 @@ static inline TCGv_i64 gen_ld64(TCGv addr, int index)
 static inline void gen_st8(TCGv val, TCGv addr, int index)
 {
     tcg_gen_qemu_st8(val, addr, index);
-    dead_tmp(val);
+    tcg_temp_free_i32(val);
 }
 static inline void gen_st16(TCGv val, TCGv addr, int index)
 {
     tcg_gen_qemu_st16(val, addr, index);
-    dead_tmp(val);
+    tcg_temp_free_i32(val);
 }
 static inline void gen_st32(TCGv val, TCGv addr, int index)
 {
     tcg_gen_qemu_st32(val, addr, index);
-    dead_tmp(val);
+    tcg_temp_free_i32(val);
 }
 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
 {
@@ -859,7 +843,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
             tcg_gen_sub_i32(var, var, offset);
         else
             tcg_gen_add_i32(var, var, offset);
-        dead_tmp(offset);
+        tcg_temp_free_i32(offset);
     }
 }
 
@@ -887,7 +871,7 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
             tcg_gen_sub_i32(var, var, offset);
         else
             tcg_gen_add_i32(var, var, offset);
-        dead_tmp(offset);
+        tcg_temp_free_i32(offset);
     }
 }
 
@@ -1065,7 +1049,7 @@ neon_reg_offset (int reg, int n)
 
 static TCGv neon_load_reg(int reg, int pass)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
     return tmp;
 }
@@ -1073,7 +1057,7 @@ static TCGv neon_load_reg(int reg, int pass)
 static void neon_store_reg(int reg, int pass, TCGv var)
 {
     tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
-    dead_tmp(var);
+    tcg_temp_free_i32(var);
 }
 
 static inline void neon_load_reg64(TCGv_i64 var, int reg)
@@ -1129,7 +1113,7 @@ static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
 
 static inline TCGv iwmmxt_load_creg(int reg)
 {
-    TCGv var = new_tmp();
+    TCGv var = tcg_temp_new_i32();
     tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
     return var;
 }
@@ -1137,7 +1121,7 @@ static inline TCGv iwmmxt_load_creg(int reg)
 static inline void iwmmxt_store_creg(int reg, TCGv var)
 {
     tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
-    dead_tmp(var);
+    tcg_temp_free_i32(var);
 }
 
 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
@@ -1268,7 +1252,7 @@ static void gen_op_iwmmxt_set_cup(void)
 
 static void gen_op_iwmmxt_setpsr_nz(void)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
     store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
 }
@@ -1300,7 +1284,7 @@ static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
         if (insn & (1 << 21))
             store_reg(s, rd, tmp);
         else
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
     } else if (insn & (1 << 21)) {
         /* Post indexed */
         tcg_gen_mov_i32(dest, tmp);
@@ -1326,13 +1310,13 @@ static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
             tmp = iwmmxt_load_creg(rd);
         }
     } else {
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         iwmmxt_load_reg(cpu_V0, rd);
         tcg_gen_trunc_i64_i32(tmp, cpu_V0);
     }
     tcg_gen_andi_i32(tmp, tmp, mask);
     tcg_gen_mov_i32(dest, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
     return 0;
 }
 
@@ -1364,14 +1348,14 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
 
         wrd = (insn >> 12) & 0xf;
-        addr = new_tmp();
+        addr = tcg_temp_new_i32();
         if (gen_iwmmxt_address(s, insn, addr)) {
-            dead_tmp(addr);
+            tcg_temp_free_i32(addr);
             return 1;
         }
         if (insn & ARM_CP_RW_BIT) {
             if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
                 iwmmxt_store_creg(wrd, tmp);
             } else {
@@ -1392,7 +1376,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
                 }
                 if (i) {
                     tcg_gen_extu_i32_i64(cpu_M0, tmp);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                 }
                 gen_op_iwmmxt_movq_wRn_M0(wrd);
             }
@@ -1402,10 +1386,10 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
                 gen_st32(tmp, addr, IS_USER(s));
             } else {
                 gen_op_iwmmxt_movq_M0_wRn(wrd);
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 if (insn & (1 << 8)) {
                     if (insn & (1 << 22)) {		/* WSTRD */
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp);
                         tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
                     } else {				/* WSTRW wRd */
                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
@@ -1422,7 +1406,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
                 }
             }
         }
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         return 0;
     }
 
@@ -1457,7 +1441,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             tmp = iwmmxt_load_creg(wrd);
             tmp2 = load_reg(s, rd);
             tcg_gen_andc_i32(tmp, tmp, tmp2);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             iwmmxt_store_creg(wrd, tmp);
             break;
         case ARM_IWMMXT_wCGR0:
@@ -1670,7 +1654,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         tcg_gen_andi_i32(tmp, tmp, 7);
         iwmmxt_load_reg(cpu_V1, rd1);
         gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         break;
@@ -1701,7 +1685,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
         tcg_temp_free(tmp3);
         tcg_temp_free(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         break;
@@ -1711,7 +1695,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         if (rd == 15 || ((insn >> 22) & 3) == 3)
             return 1;
         gen_op_iwmmxt_movq_M0_wRn(wrd);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         switch ((insn >> 22) & 3) {
         case 0:
             tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
@@ -1755,7 +1739,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         }
         tcg_gen_shli_i32(tmp, tmp, 28);
         gen_set_nzcv(tmp);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         break;
     case 0x401: case 0x405: case 0x409: case 0x40d:	/* TBCST */
         if (((insn >> 6) & 3) == 3)
@@ -1774,7 +1758,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
             break;
         }
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         break;
@@ -1782,7 +1766,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
             return 1;
         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
-        tmp2 = new_tmp();
+        tmp2 = tcg_temp_new_i32();
         tcg_gen_mov_i32(tmp2, tmp);
         switch ((insn >> 22) & 3) {
         case 0:
@@ -1803,8 +1787,8 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             break;
         }
         gen_set_nzcv(tmp);
-        dead_tmp(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp2);
+        tcg_temp_free_i32(tmp);
         break;
     case 0x01c: case 0x41c: case 0x81c: case 0xc1c:	/* WACC */
         wrd = (insn >> 12) & 0xf;
@@ -1830,7 +1814,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
             return 1;
         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
-        tmp2 = new_tmp();
+        tmp2 = tcg_temp_new_i32();
         tcg_gen_mov_i32(tmp2, tmp);
         switch ((insn >> 22) & 3) {
         case 0:
@@ -1851,8 +1835,8 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             break;
         }
         gen_set_nzcv(tmp);
-        dead_tmp(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp2);
+        tcg_temp_free_i32(tmp);
         break;
     case 0x103: case 0x503: case 0x903: case 0xd03:	/* TMOVMSK */
         rd = (insn >> 12) & 0xf;
@@ -1860,7 +1844,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
             return 1;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         switch ((insn >> 22) & 3) {
         case 0:
             gen_helper_iwmmxt_msbb(tmp, cpu_M0);
@@ -1975,9 +1959,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         wrd = (insn >> 12) & 0xf;
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             return 1;
         }
         switch ((insn >> 22) & 3) {
@@ -1991,7 +1975,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         gen_op_iwmmxt_set_cup();
@@ -2003,9 +1987,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         wrd = (insn >> 12) & 0xf;
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             return 1;
         }
         switch ((insn >> 22) & 3) {
@@ -2019,7 +2003,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         gen_op_iwmmxt_set_cup();
@@ -2031,9 +2015,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         wrd = (insn >> 12) & 0xf;
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             return 1;
         }
         switch ((insn >> 22) & 3) {
@@ -2047,7 +2031,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         gen_op_iwmmxt_set_cup();
@@ -2059,31 +2043,31 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
         wrd = (insn >> 12) & 0xf;
         rd0 = (insn >> 16) & 0xf;
         gen_op_iwmmxt_movq_M0_wRn(rd0);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         switch ((insn >> 22) & 3) {
         case 1:
             if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
                 return 1;
             }
             gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 2:
             if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
                 return 1;
             }
             gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         case 3:
             if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
                 return 1;
             }
             gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
             break;
         }
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         gen_op_iwmmxt_set_cup();
@@ -2324,12 +2308,12 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
             gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
             break;
         default:
-            dead_tmp(tmp2);
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp2);
+            tcg_temp_free_i32(tmp);
             return 1;
         }
-        dead_tmp(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp2);
+        tcg_temp_free_i32(tmp);
         gen_op_iwmmxt_movq_wRn_M0(wrd);
         gen_op_iwmmxt_set_mup();
         break;
@@ -2378,8 +2362,8 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
         default:
             return 1;
         }
-        dead_tmp(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp2);
+        tcg_temp_free_i32(tmp);
 
         gen_op_iwmmxt_movq_wRn_M0(acc);
         return 0;
@@ -2425,7 +2409,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
         if (!env->cp[cp].cp_read)
             return 1;
         gen_set_pc_im(s->pc);
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         tmp2 = tcg_const_i32(insn);
         gen_helper_get_cp(tmp, cpu_env, tmp2);
         tcg_temp_free(tmp2);
@@ -2438,7 +2422,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
         tmp2 = tcg_const_i32(insn);
         gen_helper_set_cp(cpu_env, tmp2, tmp);
         tcg_temp_free(tmp2);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
     }
     return 0;
 }
@@ -2505,7 +2489,7 @@ static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, ui
             store_cpu_field(tmp, cp15.c13_tls3);
             break;
         default:
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             return 0;
         }
     }
@@ -2577,17 +2561,17 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
 
     tmp2 = tcg_const_i32(insn);
     if (insn & ARM_CP_RW_BIT) {
-        tmp = new_tmp();
+        tmp = tcg_temp_new_i32();
         gen_helper_get_cp15(tmp, cpu_env, tmp2);
         /* If the destination register is r15 then sets condition codes.  */
         if (rd != 15)
             store_reg(s, rd, tmp);
         else
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
     } else {
         tmp = load_reg(s, rd);
         gen_helper_set_cp15(cpu_env, tmp2, tmp);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
         /* Normally we would always end the TB here, but Linux
          * arch/arm/mach-pxa/sleep.S expects two instructions following
          * an MMU enable to execute from cache.  Imitate this behaviour.  */
@@ -2622,7 +2606,7 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
 /* Move between integer and VFP cores.  */
 static TCGv gen_vfp_mrs(void)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_mov_i32(tmp, cpu_F0s);
     return tmp;
 }
@@ -2630,12 +2614,12 @@ static TCGv gen_vfp_mrs(void)
 static void gen_vfp_msr(TCGv tmp)
 {
     tcg_gen_mov_i32(cpu_F0s, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 static void gen_neon_dup_u8(TCGv var, int shift)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     if (shift)
         tcg_gen_shri_i32(var, var, shift);
     tcg_gen_ext8u_i32(var, var);
@@ -2643,25 +2627,25 @@ static void gen_neon_dup_u8(TCGv var, int shift)
     tcg_gen_or_i32(var, var, tmp);
     tcg_gen_shli_i32(tmp, var, 16);
     tcg_gen_or_i32(var, var, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 static void gen_neon_dup_low16(TCGv var)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_ext16u_i32(var, var);
     tcg_gen_shli_i32(tmp, var, 16);
     tcg_gen_or_i32(var, var, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 static void gen_neon_dup_high16(TCGv var)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_andi_i32(var, var, 0xffff0000);
     tcg_gen_shri_i32(tmp, var, 16);
     tcg_gen_or_i32(var, var, tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Disassemble a VFP instruction.  Returns nonzero if an error occured
@@ -2756,7 +2740,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             gen_neon_dup_low16(tmp);
                         }
                         for (n = 0; n <= pass * 2; n++) {
-                            tmp2 = new_tmp();
+                            tmp2 = tcg_temp_new_i32();
                             tcg_gen_mov_i32(tmp2, tmp);
                             neon_store_reg(rn, n, tmp2);
                         }
@@ -2767,12 +2751,12 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         case 0:
                             tmp2 = neon_load_reg(rn, pass);
                             gen_bfi(tmp, tmp2, tmp, offset, 0xff);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                             break;
                         case 1:
                             tmp2 = neon_load_reg(rn, pass);
                             gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                             break;
                         case 2:
                             break;
@@ -2818,7 +2802,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
                                 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
                             } else {
-                                tmp = new_tmp();
+                                tmp = tcg_temp_new_i32();
                                 gen_helper_vfp_get_fpscr(tmp, cpu_env);
                             }
                             break;
@@ -2839,7 +2823,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     if (rd == 15) {
                         /* Set the 4 flag bits in the CPSR.  */
                         gen_set_nzcv(tmp);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp);
                     } else {
                         store_reg(s, rd, tmp);
                     }
@@ -2857,7 +2841,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         case ARM_VFP_FPSCR:
                             gen_helper_vfp_set_fpscr(cpu_env, tmp);
-                            dead_tmp(tmp);
+                            tcg_temp_free_i32(tmp);
                             gen_lookup_tb(s);
                             break;
                         case ARM_VFP_FPEXC:
@@ -3084,7 +3068,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tmp = gen_vfp_mrs();
                         tcg_gen_ext16u_i32(tmp, tmp);
                         gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp);
                         break;
                     case 5: /* vcvtt.f32.f16 */
                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
@@ -3092,31 +3076,31 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tmp = gen_vfp_mrs();
                         tcg_gen_shri_i32(tmp, tmp, 16);
                         gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp);
                         break;
                     case 6: /* vcvtb.f16.f32 */
                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                           return 1;
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                         gen_mov_F0_vreg(0, rd);
                         tmp2 = gen_vfp_mrs();
                         tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
                         tcg_gen_or_i32(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         gen_vfp_msr(tmp);
                         break;
                     case 7: /* vcvtt.f16.f32 */
                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                           return 1;
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                         tcg_gen_shli_i32(tmp, tmp, 16);
                         gen_mov_F0_vreg(0, rd);
                         tmp2 = gen_vfp_mrs();
                         tcg_gen_ext16u_i32(tmp2, tmp2);
                         tcg_gen_or_i32(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         gen_vfp_msr(tmp);
                         break;
                     case 8: /* cmp */
@@ -3310,7 +3294,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
             else
                 rd = VFP_SREG_D(insn);
             if (s->thumb && rn == 15) {
-                addr = new_tmp();
+                addr = tcg_temp_new_i32();
                 tcg_gen_movi_i32(addr, s->pc & ~2);
             } else {
                 addr = load_reg(s, rn);
@@ -3328,7 +3312,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     gen_mov_F0_vreg(dp, rd);
                     gen_vfp_st(s, dp, addr);
                 }
-                dead_tmp(addr);
+                tcg_temp_free_i32(addr);
             } else {
                 /* load/store multiple */
                 if (dp)
@@ -3368,7 +3352,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         tcg_gen_addi_i32(addr, addr, offset);
                     store_reg(s, rn, addr);
                 } else {
-                    dead_tmp(addr);
+                    tcg_temp_free_i32(addr);
                 }
             }
         }
@@ -3467,7 +3451,7 @@ static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
     } else {
         gen_set_cpsr(t0, mask);
     }
-    dead_tmp(t0);
+    tcg_temp_free_i32(t0);
     gen_lookup_tb(s);
     return 0;
 }
@@ -3476,7 +3460,7 @@ static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
 {
     TCGv tmp;
-    tmp = new_tmp();
+    tmp = tcg_temp_new_i32();
     tcg_gen_movi_i32(tmp, val);
     return gen_set_psr(s, mask, spsr, tmp);
 }
@@ -3488,7 +3472,7 @@ static void gen_exception_return(DisasContext *s, TCGv pc)
     store_reg(s, 15, pc);
     tmp = load_cpu_field(spsr);
     gen_set_cpsr(tmp, 0xffffffff);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
     s->is_jmp = DISAS_UPDATE;
 }
 
@@ -3496,7 +3480,7 @@ static void gen_exception_return(DisasContext *s, TCGv pc)
 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
 {
     gen_set_cpsr(cpsr, 0xffffffff);
-    dead_tmp(cpsr);
+    tcg_temp_free_i32(cpsr);
     store_reg(s, 15, pc);
     s->is_jmp = DISAS_UPDATE;
 }
@@ -3506,7 +3490,7 @@ gen_set_condexec (DisasContext *s)
 {
     if (s->condexec_mask) {
         uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
-        TCGv tmp = new_tmp();
+        TCGv tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, val);
         store_cpu_field(tmp, condexec_bits);
     }
@@ -3612,7 +3596,7 @@ static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
 
 static TCGv neon_load_scratch(int scratch)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
     return tmp;
 }
@@ -3620,7 +3604,7 @@ static TCGv neon_load_scratch(int scratch)
 static void neon_store_scratch(int scratch, TCGv var)
 {
     tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
-    dead_tmp(var);
+    tcg_temp_free_i32(var);
 }
 
 static inline TCGv neon_get_scalar(int size, int reg)
@@ -3721,8 +3705,8 @@ static void gen_neon_trn_u8(TCGv t0, TCGv t1)
 {
     TCGv rd, tmp;
 
-    rd = new_tmp();
-    tmp = new_tmp();
+    rd = tcg_temp_new_i32();
+    tmp = tcg_temp_new_i32();
 
     tcg_gen_shli_i32(rd, t0, 8);
     tcg_gen_andi_i32(rd, rd, 0xff00ff00);
@@ -3735,16 +3719,16 @@ static void gen_neon_trn_u8(TCGv t0, TCGv t1)
     tcg_gen_or_i32(t1, t1, tmp);
     tcg_gen_mov_i32(t0, rd);
 
-    dead_tmp(tmp);
-    dead_tmp(rd);
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(rd);
 }
 
 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
 {
     TCGv rd, tmp;
 
-    rd = new_tmp();
-    tmp = new_tmp();
+    rd = tcg_temp_new_i32();
+    tmp = tcg_temp_new_i32();
 
     tcg_gen_shli_i32(rd, t0, 16);
     tcg_gen_andi_i32(tmp, t1, 0xffff);
@@ -3754,8 +3738,8 @@ static void gen_neon_trn_u16(TCGv t0, TCGv t1)
     tcg_gen_or_i32(t1, t1, tmp);
     tcg_gen_mov_i32(t0, rd);
 
-    dead_tmp(tmp);
-    dead_tmp(rd);
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(rd);
 }
 
 
@@ -3804,7 +3788,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
     rn = (insn >> 16) & 0xf;
     rm = insn & 0xf;
     load = (insn & (1 << 21)) != 0;
-    addr = new_tmp();
+    addr = tcg_temp_new_i32();
     if ((insn & (1 << 23)) == 0) {
         /* Load store all elements.  */
         op = (insn >> 8) & 0xf;
@@ -3856,11 +3840,11 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tcg_gen_addi_i32(addr, addr, stride);
                             tcg_gen_shli_i32(tmp2, tmp2, 16);
                             tcg_gen_or_i32(tmp, tmp, tmp2);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                             neon_store_reg(rd, pass, tmp);
                         } else {
                             tmp = neon_load_reg(rd, pass);
-                            tmp2 = new_tmp();
+                            tmp2 = tcg_temp_new_i32();
                             tcg_gen_shri_i32(tmp2, tmp, 16);
                             gen_st16(tmp, addr, IS_USER(s));
                             tcg_gen_addi_i32(addr, addr, stride);
@@ -3878,14 +3862,14 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 } else {
                                     tcg_gen_shli_i32(tmp, tmp, n * 8);
                                     tcg_gen_or_i32(tmp2, tmp2, tmp);
-                                    dead_tmp(tmp);
+                                    tcg_temp_free_i32(tmp);
                                 }
                             }
                             neon_store_reg(rd, pass, tmp2);
                         } else {
                             tmp2 = neon_load_reg(rd, pass);
                             for (n = 0; n < 4; n++) {
-                                tmp = new_tmp();
+                                tmp = tcg_temp_new_i32();
                                 if (n == 0) {
                                     tcg_gen_mov_i32(tmp, tmp2);
                                 } else {
@@ -3894,7 +3878,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_st8(tmp, addr, IS_USER(s));
                                 tcg_gen_addi_i32(addr, addr, stride);
                             }
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                     }
                 }
@@ -3931,7 +3915,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     abort();
                 }
                 tcg_gen_addi_i32(addr, addr, 1 << size);
-                tmp2 = new_tmp();
+                tmp2 = tcg_temp_new_i32();
                 tcg_gen_mov_i32(tmp2, tmp);
                 neon_store_reg(rd, 0, tmp2);
                 neon_store_reg(rd, 1, tmp);
@@ -3977,7 +3961,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     if (size != 2) {
                         tmp2 = neon_load_reg(rd, pass);
                         gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                     }
                     neon_store_reg(rd, pass, tmp);
                 } else { /* Store */
@@ -4002,7 +3986,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
             stride = nregs * (1 << size);
         }
     }
-    dead_tmp(addr);
+    tcg_temp_free_i32(addr);
     if (rm != 15) {
         TCGv base;
 
@@ -4013,7 +3997,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
             TCGv index;
             index = load_reg(s, rm);
             tcg_gen_add_i32(base, base, index);
-            dead_tmp(index);
+            tcg_temp_free_i32(index);
         }
         store_reg(s, rn, base);
     }
@@ -4119,7 +4103,7 @@ static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
         default: abort();
         }
     }
-    dead_tmp(src);
+    tcg_temp_free_i32(src);
 }
 
 static inline void gen_neon_addl(int size)
@@ -4184,8 +4168,8 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
     /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
        Don't forget to clean them now.  */
     if (size < 2) {
-      dead_tmp(a);
-      dead_tmp(b);
+        tcg_temp_free_i32(a);
+        tcg_temp_free_i32(b);
     }
 }
 
@@ -4389,17 +4373,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             case 5: /* VBSL */
                 tmp3 = neon_load_reg(rd, pass);
                 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
-                dead_tmp(tmp3);
+                tcg_temp_free_i32(tmp3);
                 break;
             case 6: /* VBIT */
                 tmp3 = neon_load_reg(rd, pass);
                 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
-                dead_tmp(tmp3);
+                tcg_temp_free_i32(tmp3);
                 break;
             case 7: /* VBIF */
                 tmp3 = neon_load_reg(rd, pass);
                 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
-                dead_tmp(tmp3);
+                tcg_temp_free_i32(tmp3);
                 break;
             }
             break;
@@ -4438,7 +4422,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             break;
         case 15: /* VABA */
             GEN_NEON_INTEGER_OP(abd);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             tmp2 = neon_load_reg(rd, pass);
             gen_neon_add(size, tmp, tmp2);
             break;
@@ -4479,7 +4463,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
             default: return 1;
             }
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             tmp2 = neon_load_reg(rd, pass);
             if (u) { /* VMLS */
                 gen_neon_rsb(size, tmp, tmp2);
@@ -4551,7 +4535,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
         case 27: /* Float multiply.  */
             gen_helper_neon_mul_f32(tmp, tmp, tmp2);
             if (!u) {
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 tmp2 = neon_load_reg(rd, pass);
                 if (size == 0) {
                     gen_helper_neon_add_f32(tmp, tmp, tmp2);
@@ -4593,7 +4577,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
         default:
             abort();
         }
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
 
         /* Save the result.  For elementwise operations we can put it
            straight into the destination register.  For pairwise operations
@@ -4726,7 +4710,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     } else { /* size < 3 */
                         /* Operands in T0 and T1.  */
                         tmp = neon_load_reg(rm, pass);
-                        tmp2 = new_tmp();
+                        tmp2 = tcg_temp_new_i32();
                         tcg_gen_movi_i32(tmp2, imm);
                         switch (op) {
                         case 0:  /* VSHR */
@@ -4775,13 +4759,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             GEN_NEON_INTEGER_OP_ENV(qshl);
                             break;
                         }
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
 
                         if (op == 1 || op == 3) {
                             /* Accumulate.  */
                             tmp2 = neon_load_reg(rd, pass);
                             gen_neon_add(size, tmp, tmp2);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         } else if (op == 4 || (op == 5 && u)) {
                             /* Insert */
                             switch (size) {
@@ -4817,7 +4801,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tcg_gen_andi_i32(tmp, tmp, mask);
                             tcg_gen_andi_i32(tmp2, tmp2, ~mask);
                             tcg_gen_or_i32(tmp, tmp, tmp2);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         neon_store_reg(rd, pass, tmp);
                     }
@@ -4853,7 +4837,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
                             }
                         }
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
                         neon_store_reg(rd, pass, tmp);
                     } /* for pass */
@@ -4885,9 +4869,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         gen_neon_shift_narrow(size, tmp3, tmp2, q,
                                               input_unsigned);
                         tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
-                        dead_tmp(tmp);
-                        dead_tmp(tmp3);
-                        tmp = new_tmp();
+                        tcg_temp_free_i32(tmp);
+                        tcg_temp_free_i32(tmp3);
+                        tmp = tcg_temp_new_i32();
                         gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
                         neon_store_reg(rd, pass, tmp);
                     } /* for pass */
@@ -5016,7 +5000,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                 } else {
                     /* VMOV, VMVN.  */
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     if (op == 14 && invert) {
                         uint32_t val;
                         val = 0;
@@ -5133,8 +5117,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             break;
                         default: abort();
                         }
-                        dead_tmp(tmp2);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp2);
+                        tcg_temp_free_i32(tmp);
                         break;
                     case 8: case 9: case 10: case 11: case 12: case 13:
                         /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
@@ -5142,8 +5126,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         break;
                     case 14: /* Polynomial VMULL */
                         gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
-                        dead_tmp(tmp2);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp2);
+                        tcg_temp_free_i32(tmp);
                         break;
                     default: /* 15 is RESERVED.  */
                         return 1;
@@ -5175,7 +5159,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg64(cpu_V0, rd + pass);
                     } else if (op == 4 || op == 6) {
                         /* Narrowing operation.  */
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         if (!u) {
                             switch (size) {
                             case 0:
@@ -5255,7 +5239,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             default: return 1;
                             }
                         }
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         if (op < 8) {
                             /* Accumulate.  */
                             tmp2 = neon_load_reg(rd, pass);
@@ -5275,7 +5259,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             default:
                                 abort();
                             }
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         neon_store_reg(rd, pass, tmp);
                     }
@@ -5292,7 +5276,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tmp2 = neon_get_scalar(size, rm);
                     /* We need a copy of tmp2 because gen_neon_mull
                      * deletes it during pass 0.  */
-                    tmp4 = new_tmp();
+                    tmp4 = tcg_temp_new_i32();
                     tcg_gen_mov_i32(tmp4, tmp2);
                     tmp3 = neon_load_reg(rn, 1);
 
@@ -5472,7 +5456,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     TCGV_UNUSED(tmp2);
                     for (pass = 0; pass < 2; pass++) {
                         neon_load_reg64(cpu_V0, rm + pass);
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
                         if (pass == 0) {
                             tmp2 = tmp;
@@ -5498,8 +5482,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 case 44: /* VCVT.F16.F32 */
                     if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                       return 1;
-                    tmp = new_tmp();
-                    tmp2 = new_tmp();
+                    tmp = tcg_temp_new_i32();
+                    tmp2 = tcg_temp_new_i32();
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
                     gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
@@ -5510,17 +5494,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
                     tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
                     neon_store_reg(rd, 0, tmp2);
-                    tmp2 = new_tmp();
+                    tmp2 = tcg_temp_new_i32();
                     gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
                     tcg_gen_shli_i32(tmp2, tmp2, 16);
                     tcg_gen_or_i32(tmp2, tmp2, tmp);
                     neon_store_reg(rd, 1, tmp2);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     break;
                 case 46: /* VCVT.F32.F16 */
                     if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
                       return 1;
-                    tmp3 = new_tmp();
+                    tmp3 = tcg_temp_new_i32();
                     tmp = neon_load_reg(rm, 0);
                     tmp2 = neon_load_reg(rm, 1);
                     tcg_gen_ext16u_i32(tmp3, tmp);
@@ -5529,15 +5513,15 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     tcg_gen_shri_i32(tmp3, tmp, 16);
                     gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     tcg_gen_ext16u_i32(tmp3, tmp2);
                     gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
                     tcg_gen_shri_i32(tmp3, tmp2, 16);
                     gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
                     tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
-                    dead_tmp(tmp2);
-                    dead_tmp(tmp3);
+                    tcg_temp_free_i32(tmp2);
+                    tcg_temp_free_i32(tmp3);
                     break;
                 default:
                 elementwise:
@@ -5735,18 +5719,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 if (insn & (1 << 6)) {
                     tmp = neon_load_reg(rd, 0);
                 } else {
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp, 0);
                 }
                 tmp2 = neon_load_reg(rm, 0);
                 tmp4 = tcg_const_i32(rn);
                 tmp5 = tcg_const_i32(n);
                 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
                 if (insn & (1 << 6)) {
                     tmp = neon_load_reg(rd, 1);
                 } else {
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp, 0);
                 }
                 tmp3 = neon_load_reg(rm, 1);
@@ -5755,7 +5739,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 tcg_temp_free_i32(tmp4);
                 neon_store_reg(rd, 0, tmp2);
                 neon_store_reg(rd, 1, tmp3);
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
             } else if ((insn & 0x380) == 0) {
                 /* VDUP */
                 if (insn & (1 << 19)) {
@@ -5772,11 +5756,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         gen_neon_dup_low16(tmp);
                 }
                 for (pass = 0; pass < (q ? 4 : 2); pass++) {
-                    tmp2 = new_tmp();
+                    tmp2 = tcg_temp_new_i32();
                     tcg_gen_mov_i32(tmp2, tmp);
                     neon_store_reg(rd, pass, tmp2);
                 }
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
             } else {
                 return 1;
             }
@@ -5833,7 +5817,7 @@ static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
                 return 1;
             tmp = load_reg(s, rt);
             gen_helper_set_teecr(cpu_env, tmp);
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             return 0;
         }
         if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
@@ -5894,10 +5878,10 @@ static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
 {
     TCGv tmp;
-    tmp = new_tmp();
+    tmp = tcg_temp_new_i32();
     tcg_gen_trunc_i64_i32(tmp, val);
     store_reg(s, rlow, tmp);
-    tmp = new_tmp();
+    tmp = tcg_temp_new_i32();
     tcg_gen_shri_i64(val, val, 32);
     tcg_gen_trunc_i64_i32(tmp, val);
     store_reg(s, rhigh, tmp);
@@ -5913,7 +5897,7 @@ static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
     tmp = tcg_temp_new_i64();
     tmp2 = load_reg(s, rlow);
     tcg_gen_extu_i32_i64(tmp, tmp2);
-    dead_tmp(tmp2);
+    tcg_temp_free_i32(tmp2);
     tcg_gen_add_i64(val, val, tmp);
     tcg_temp_free_i64(tmp);
 }
@@ -5930,8 +5914,8 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
     tmph = load_reg(s, rhigh);
     tmp = tcg_temp_new_i64();
     tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
-    dead_tmp(tmpl);
-    dead_tmp(tmph);
+    tcg_temp_free_i32(tmpl);
+    tcg_temp_free_i32(tmph);
     tcg_gen_add_i64(val, val, tmp);
     tcg_temp_free_i64(tmp);
 }
@@ -5939,10 +5923,10 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
 /* Set N and Z flags from a 64-bit value.  */
 static void gen_logicq_cc(TCGv_i64 val)
 {
-    TCGv tmp = new_tmp();
+    TCGv tmp = tcg_temp_new_i32();
     gen_helper_logicq_cc(tmp, val);
     gen_logic_CC(tmp);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
 }
 
 /* Load/Store exclusive instructions are implemented by remembering
@@ -5976,10 +5960,10 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
     tcg_gen_mov_i32(cpu_exclusive_val, tmp);
     store_reg(s, rt, tmp);
     if (size == 3) {
-        TCGv tmp2 = new_tmp();
+        TCGv tmp2 = tcg_temp_new_i32();
         tcg_gen_addi_i32(tmp2, addr, 4);
         tmp = gen_ld32(tmp2, IS_USER(s));
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_mov_i32(cpu_exclusive_high, tmp);
         store_reg(s, rt2, tmp);
     }
@@ -6032,14 +6016,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
         abort();
     }
     tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
-    dead_tmp(tmp);
+    tcg_temp_free_i32(tmp);
     if (size == 3) {
-        TCGv tmp2 = new_tmp();
+        TCGv tmp2 = tcg_temp_new_i32();
         tcg_gen_addi_i32(tmp2, addr, 4);
         tmp = gen_ld32(tmp2, IS_USER(s));
-        dead_tmp(tmp2);
+        tcg_temp_free_i32(tmp2);
         tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
     }
     tmp = load_reg(s, rt);
     switch (size) {
@@ -6160,7 +6144,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 goto illegal_op;
             ARCH(6);
             op1 = (insn & 0x1f);
-            addr = new_tmp();
+            addr = tcg_temp_new_i32();
             tmp = tcg_const_i32(op1);
             gen_helper_get_r13_banked(addr, cpu_env, tmp);
             tcg_temp_free_i32(tmp);
@@ -6193,9 +6177,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 tmp = tcg_const_i32(op1);
                 gen_helper_set_r13_banked(cpu_env, tmp, addr);
                 tcg_temp_free_i32(tmp);
-                dead_tmp(addr);
+                tcg_temp_free_i32(addr);
             } else {
-                dead_tmp(addr);
+                tcg_temp_free_i32(addr);
             }
             return;
         } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
@@ -6233,7 +6217,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     tcg_gen_addi_i32(addr, addr, offset);
                 store_reg(s, rn, addr);
             } else {
-                dead_tmp(addr);
+                tcg_temp_free_i32(addr);
             }
             gen_rfe(s, tmp, tmp2);
             return;
@@ -6242,7 +6226,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             int32_t offset;
 
             val = (uint32_t)s->pc;
-            tmp = new_tmp();
+            tmp = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp, val);
             store_reg(s, 14, tmp);
             /* Sign-extend the 24-bit offset */
@@ -6306,7 +6290,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
             if ((insn & (1 << 22)) == 0) {
                 /* MOVW */
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_movi_i32(tmp, val);
             } else {
                 /* MOVT */
@@ -6353,7 +6337,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         goto illegal_op;
                     tmp = load_cpu_field(spsr);
                 } else {
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     gen_helper_cpsr_read(tmp);
                 }
                 store_reg(s, rd, tmp);
@@ -6390,7 +6374,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
 
             /* branch link/exchange thumb (blx) */
             tmp = load_reg(s, rm);
-            tmp2 = new_tmp();
+            tmp2 = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp2, s->pc);
             store_reg(s, 14, tmp2);
             gen_bx(s, tmp);
@@ -6406,7 +6390,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 gen_helper_sub_saturate(tmp, tmp, tmp2);
             else
                 gen_helper_add_saturate(tmp, tmp, tmp2);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             store_reg(s, rd, tmp);
             break;
         case 7:
@@ -6436,13 +6420,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     gen_sxth(tmp2);
                 tmp64 = gen_muls_i64_i32(tmp, tmp2);
                 tcg_gen_shri_i64(tmp64, tmp64, 16);
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_trunc_i64_i32(tmp, tmp64);
                 tcg_temp_free_i64(tmp64);
                 if ((sh & 2) == 0) {
                     tmp2 = load_reg(s, rn);
                     gen_helper_add_setq(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
                 store_reg(s, rd, tmp);
             } else {
@@ -6450,11 +6434,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 tmp = load_reg(s, rm);
                 tmp2 = load_reg(s, rs);
                 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 if (op1 == 2) {
                     tmp64 = tcg_temp_new_i64();
                     tcg_gen_ext_i32_i64(tmp64, tmp);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     gen_addq(s, tmp64, rn, rd);
                     gen_storeq_reg(s, rn, rd, tmp64);
                     tcg_temp_free_i64(tmp64);
@@ -6462,7 +6446,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     if (op1 == 0) {
                         tmp2 = load_reg(s, rn);
                         gen_helper_add_setq(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                     }
                     store_reg(s, rd, tmp);
                 }
@@ -6488,7 +6472,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             if (shift) {
                 val = (val >> shift) | (val << (32 - shift));
             }
-            tmp2 = new_tmp();
+            tmp2 = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp2, val);
             if (logic_cc && shift) {
                 gen_set_CF_bit31(tmp2);
@@ -6591,26 +6575,26 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 tcg_gen_and_i32(tmp, tmp, tmp2);
                 gen_logic_CC(tmp);
             }
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             break;
         case 0x09:
             if (set_cc) {
                 tcg_gen_xor_i32(tmp, tmp, tmp2);
                 gen_logic_CC(tmp);
             }
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             break;
         case 0x0a:
             if (set_cc) {
                 gen_helper_sub_cc(tmp, tmp, tmp2);
             }
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             break;
         case 0x0b:
             if (set_cc) {
                 gen_helper_add_cc(tmp, tmp, tmp2);
             }
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             break;
         case 0x0c:
             tcg_gen_or_i32(tmp, tmp, tmp2);
@@ -6650,7 +6634,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             break;
         }
         if (op1 != 0x0f && op1 != 0x0d) {
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
         }
     } else {
         /* other instructions */
@@ -6673,18 +6657,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         tmp = load_reg(s, rs);
                         tmp2 = load_reg(s, rm);
                         tcg_gen_mul_i32(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         if (insn & (1 << 22)) {
                             /* Subtract (mls) */
                             ARCH(6T2);
                             tmp2 = load_reg(s, rn);
                             tcg_gen_sub_i32(tmp, tmp2, tmp);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         } else if (insn & (1 << 21)) {
                             /* Add */
                             tmp2 = load_reg(s, rn);
                             tcg_gen_add_i32(tmp, tmp, tmp2);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         if (insn & (1 << 20))
                             gen_logic_CC(tmp);
@@ -6788,7 +6772,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             tmp2 = gen_ld32(addr, IS_USER(s));
                             gen_st32(tmp, addr, IS_USER(s));
                         }
-                        dead_tmp(addr);
+                        tcg_temp_free_i32(addr);
                         store_reg(s, rd, tmp2);
                     }
                 }
@@ -6855,7 +6839,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         tcg_gen_addi_i32(addr, addr, address_offset);
                     store_reg(s, rn, addr);
                 } else {
-                    dead_tmp(addr);
+                    tcg_temp_free_i32(addr);
                 }
                 if (load) {
                     /* Complete the load.  */
@@ -6884,7 +6868,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     if ((op1 & 3) == 0 || sh == 5 || sh == 6)
                         goto illegal_op;
                     gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                     store_reg(s, rd, tmp);
                     break;
                 case 1:
@@ -6908,7 +6892,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
                         }
                         tcg_gen_or_i32(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x00200020) == 0x00200000) {
                         /* [us]sat */
@@ -6944,11 +6928,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         /* Select bytes.  */
                         tmp = load_reg(s, rn);
                         tmp2 = load_reg(s, rm);
-                        tmp3 = new_tmp();
+                        tmp3 = tcg_temp_new_i32();
                         tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
                         gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
-                        dead_tmp(tmp3);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp3);
+                        tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x000003e0) == 0x00000060) {
                         tmp = load_reg(s, rm);
@@ -6973,7 +6957,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                                 gen_add16(tmp, tmp2);
                             } else {
                                 tcg_gen_add_i32(tmp, tmp, tmp2);
-                                dead_tmp(tmp2);
+                                tcg_temp_free_i32(tmp2);
                             }
                         }
                         store_reg(s, rd, tmp);
@@ -7018,7 +7002,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
                         }
                         tcg_gen_shri_i64(tmp64, tmp64, 32);
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         tcg_gen_trunc_i64_i32(tmp, tmp64);
                         tcg_temp_free_i64(tmp64);
                         store_reg(s, rn, tmp);
@@ -7032,12 +7016,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         } else {
                             tcg_gen_add_i32(tmp, tmp, tmp2);
                         }
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         if (insn & (1 << 22)) {
                             /* smlald, smlsld */
                             tmp64 = tcg_temp_new_i64();
                             tcg_gen_ext_i32_i64(tmp64, tmp);
-                            dead_tmp(tmp);
+                            tcg_temp_free_i32(tmp);
                             gen_addq(s, tmp64, rd, rn);
                             gen_storeq_reg(s, rd, rn, tmp64);
                             tcg_temp_free_i64(tmp64);
@@ -7047,7 +7031,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                               {
                                 tmp2 = load_reg(s, rd);
                                 gen_helper_add_setq(tmp, tmp, tmp2);
-                                dead_tmp(tmp2);
+                                tcg_temp_free_i32(tmp2);
                               }
                             store_reg(s, rn, tmp);
                         }
@@ -7061,11 +7045,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         tmp = load_reg(s, rm);
                         tmp2 = load_reg(s, rs);
                         gen_helper_usad8(tmp, tmp, tmp2);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         if (rd != 15) {
                             tmp2 = load_reg(s, rd);
                             tcg_gen_add_i32(tmp, tmp, tmp2);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         store_reg(s, rn, tmp);
                         break;
@@ -7076,7 +7060,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         i = (insn >> 16) & 0x1f;
                         i = i + 1 - shift;
                         if (rm == 15) {
-                            tmp = new_tmp();
+                            tmp = tcg_temp_new_i32();
                             tcg_gen_movi_i32(tmp, 0);
                         } else {
                             tmp = load_reg(s, rm);
@@ -7084,7 +7068,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         if (i != 32) {
                             tmp2 = load_reg(s, rd);
                             gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         store_reg(s, rd, tmp);
                         break;
@@ -7150,7 +7134,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             } else if (insn & (1 << 21)) {
                 store_reg(s, rn, tmp2);
             } else {
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
             }
             if (insn & (1 << 20)) {
                 /* Complete the load.  */
@@ -7216,7 +7200,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                                 tmp2 = tcg_const_i32(i);
                                 gen_helper_set_user_reg(tmp2, tmp);
                                 tcg_temp_free_i32(tmp2);
-                                dead_tmp(tmp);
+                                tcg_temp_free_i32(tmp);
                             } else if (i == rn) {
                                 loaded_var = tmp;
                                 loaded_base = 1;
@@ -7228,10 +7212,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             if (i == 15) {
                                 /* special case: r15 = PC + 8 */
                                 val = (long)s->pc + 4;
-                                tmp = new_tmp();
+                                tmp = tcg_temp_new_i32();
                                 tcg_gen_movi_i32(tmp, val);
                             } else if (user) {
-                                tmp = new_tmp();
+                                tmp = tcg_temp_new_i32();
                                 tmp2 = tcg_const_i32(i);
                                 gen_helper_get_user_reg(tmp, tmp2);
                                 tcg_temp_free_i32(tmp2);
@@ -7267,7 +7251,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     }
                     store_reg(s, rn, addr);
                 } else {
-                    dead_tmp(addr);
+                    tcg_temp_free_i32(addr);
                 }
                 if (loaded_base) {
                     store_reg(s, rn, loaded_var);
@@ -7276,7 +7260,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                     /* Restore CPSR from SPSR.  */
                     tmp = load_cpu_field(spsr);
                     gen_set_cpsr(tmp, 0xffffffff);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     s->is_jmp = DISAS_UPDATE;
                 }
             }
@@ -7289,7 +7273,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 /* branch (and link) */
                 val = (int32_t)s->pc;
                 if (insn & (1 << 24)) {
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp, val);
                     store_reg(s, 14, tmp);
                 }
@@ -7427,7 +7411,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             tcg_gen_addi_i32(tmp, tmp, offset);
             tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
 
-            tmp2 = new_tmp();
+            tmp2 = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp2, s->pc | 1);
             store_reg(s, 14, tmp2);
             gen_bx(s, tmp);
@@ -7439,7 +7423,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             tmp = load_reg(s, 14);
             tcg_gen_addi_i32(tmp, tmp, offset);
 
-            tmp2 = new_tmp();
+            tmp2 = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp2, s->pc | 1);
             store_reg(s, 14, tmp2);
             gen_bx(s, tmp);
@@ -7478,7 +7462,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             if (insn & 0x01200000) {
                 /* Load/store doubleword.  */
                 if (rn == 15) {
-                    addr = new_tmp();
+                    addr = tcg_temp_new_i32();
                     tcg_gen_movi_i32(addr, s->pc & ~3);
                 } else {
                     addr = load_reg(s, rn);
@@ -7512,7 +7496,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     tcg_gen_addi_i32(addr, addr, offset - 4);
                     store_reg(s, rn, addr);
                 } else {
-                    dead_tmp(addr);
+                    tcg_temp_free_i32(addr);
                 }
             } else if ((insn & (1 << 23)) == 0) {
                 /* Load/store exclusive word.  */
@@ -7528,7 +7512,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             } else if ((insn & (1 << 6)) == 0) {
                 /* Table Branch.  */
                 if (rn == 15) {
-                    addr = new_tmp();
+                    addr = tcg_temp_new_i32();
                     tcg_gen_movi_i32(addr, s->pc);
                 } else {
                     addr = load_reg(s, rn);
@@ -7538,13 +7522,13 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 if (insn & (1 << 4)) {
                     /* tbh */
                     tcg_gen_add_i32(addr, addr, tmp);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     tmp = gen_ld16u(addr, IS_USER(s));
                 } else { /* tbb */
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     tmp = gen_ld8u(addr, IS_USER(s));
                 }
-                dead_tmp(addr);
+                tcg_temp_free_i32(addr);
                 tcg_gen_shli_i32(tmp, tmp, 1);
                 tcg_gen_addi_i32(tmp, tmp, s->pc);
                 store_reg(s, 15, tmp);
@@ -7588,13 +7572,13 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                         }
                         store_reg(s, rn, addr);
                     } else {
-                        dead_tmp(addr);
+                        tcg_temp_free_i32(addr);
                     }
                     gen_rfe(s, tmp, tmp2);
                 } else {
                     /* srs */
                     op = (insn & 0x1f);
-                    addr = new_tmp();
+                    addr = tcg_temp_new_i32();
                     tmp = tcg_const_i32(op);
                     gen_helper_get_r13_banked(addr, cpu_env, tmp);
                     tcg_temp_free_i32(tmp);
@@ -7604,7 +7588,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     tmp = load_reg(s, 14);
                     gen_st32(tmp, addr, 0);
                     tcg_gen_addi_i32(addr, addr, 4);
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     gen_helper_cpsr_read(tmp);
                     gen_st32(tmp, addr, 0);
                     if (insn & (1 << 21)) {
@@ -7617,7 +7601,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                         gen_helper_set_r13_banked(cpu_env, tmp, addr);
                         tcg_temp_free_i32(tmp);
                     } else {
-                        dead_tmp(addr);
+                        tcg_temp_free_i32(addr);
                     }
                 }
             } else {
@@ -7661,7 +7645,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                         goto illegal_op;
                     store_reg(s, rn, addr);
                 } else {
-                    dead_tmp(addr);
+                    tcg_temp_free_i32(addr);
                 }
             }
         }
@@ -7689,12 +7673,12 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
             }
             tcg_gen_or_i32(tmp, tmp, tmp2);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             store_reg(s, rd, tmp);
         } else {
             /* Data processing register constant shift.  */
             if (rn == 15) {
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_movi_i32(tmp, 0);
             } else {
                 tmp = load_reg(s, rn);
@@ -7708,11 +7692,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
             if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
                 goto illegal_op;
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             if (rd != 15) {
                 store_reg(s, rd, tmp);
             } else {
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
             }
         }
         break;
@@ -7756,7 +7740,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     gen_add16(tmp, tmp2);
                 } else {
                     tcg_gen_add_i32(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
             }
             store_reg(s, rd, tmp);
@@ -7769,7 +7753,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             tmp = load_reg(s, rn);
             tmp2 = load_reg(s, rm);
             gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             store_reg(s, rd, tmp);
             break;
         case 3: /* Other data processing.  */
@@ -7784,7 +7768,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     gen_helper_sub_saturate(tmp, tmp2, tmp);
                 else
                     gen_helper_add_saturate(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
             } else {
                 tmp = load_reg(s, rn);
                 switch (op) {
@@ -7802,11 +7786,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     break;
                 case 0x10: /* sel */
                     tmp2 = load_reg(s, rm);
-                    tmp3 = new_tmp();
+                    tmp3 = tcg_temp_new_i32();
                     tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
                     gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
-                    dead_tmp(tmp3);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp3);
+                    tcg_temp_free_i32(tmp2);
                     break;
                 case 0x18: /* clz */
                     gen_helper_clz(tmp, tmp);
@@ -7824,23 +7808,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             switch ((insn >> 20) & 7) {
             case 0: /* 32 x 32 -> 32 */
                 tcg_gen_mul_i32(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 if (rs != 15) {
                     tmp2 = load_reg(s, rs);
                     if (op)
                         tcg_gen_sub_i32(tmp, tmp2, tmp);
                     else
                         tcg_gen_add_i32(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
                 break;
             case 1: /* 16 x 16 -> 32 */
                 gen_mulxy(tmp, tmp2, op & 2, op & 1);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 if (rs != 15) {
                     tmp2 = load_reg(s, rs);
                     gen_helper_add_setq(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
                 break;
             case 2: /* Dual multiply add.  */
@@ -7854,12 +7838,12 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 } else {
                     tcg_gen_add_i32(tmp, tmp, tmp2);
                 }
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 if (rs != 15)
                   {
                     tmp2 = load_reg(s, rs);
                     gen_helper_add_setq(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                   }
                 break;
             case 3: /* 32 * 16 -> 32msb */
@@ -7869,14 +7853,14 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     gen_sxth(tmp2);
                 tmp64 = gen_muls_i64_i32(tmp, tmp2);
                 tcg_gen_shri_i64(tmp64, tmp64, 16);
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_trunc_i64_i32(tmp, tmp64);
                 tcg_temp_free_i64(tmp64);
                 if (rs != 15)
                   {
                     tmp2 = load_reg(s, rs);
                     gen_helper_add_setq(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                   }
                 break;
             case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
@@ -7893,17 +7877,17 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
                 }
                 tcg_gen_shri_i64(tmp64, tmp64, 32);
-                tmp = new_tmp();
+                tmp = tcg_temp_new_i32();
                 tcg_gen_trunc_i64_i32(tmp, tmp64);
                 tcg_temp_free_i64(tmp64);
                 break;
             case 7: /* Unsigned sum of absolute differences.  */
                 gen_helper_usad8(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 if (rs != 15) {
                     tmp2 = load_reg(s, rs);
                     tcg_gen_add_i32(tmp, tmp, tmp2);
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
                 break;
             }
@@ -7921,7 +7905,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     gen_helper_udiv(tmp, tmp, tmp2);
                 else
                     gen_helper_sdiv(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 store_reg(s, rd, tmp);
             } else if ((op & 0xe) == 0xc) {
                 /* Dual multiply accumulate long.  */
@@ -7933,11 +7917,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 } else {
                     tcg_gen_add_i32(tmp, tmp, tmp2);
                 }
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 /* BUGFIX */
                 tmp64 = tcg_temp_new_i64();
                 tcg_gen_ext_i32_i64(tmp64, tmp);
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp);
                 gen_addq(s, tmp64, rs, rd);
                 gen_storeq_reg(s, rs, rd, tmp64);
                 tcg_temp_free_i64(tmp64);
@@ -7949,10 +7933,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     if (op & 8) {
                         /* smlalxy */
                         gen_mulxy(tmp, tmp2, op & 2, op & 1);
-                        dead_tmp(tmp2);
+                        tcg_temp_free_i32(tmp2);
                         tmp64 = tcg_temp_new_i64();
                         tcg_gen_ext_i32_i64(tmp64, tmp);
-                        dead_tmp(tmp);
+                        tcg_temp_free_i32(tmp);
                     } else {
                         /* Signed 64-bit multiply  */
                         tmp64 = gen_muls_i64_i32(tmp, tmp2);
@@ -8032,7 +8016,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                             addr = tcg_const_i32(insn & 0xff);
                             gen_helper_v7m_msr(cpu_env, addr, tmp);
                             tcg_temp_free_i32(addr);
-                            dead_tmp(tmp);
+                            tcg_temp_free_i32(tmp);
                             gen_lookup_tb(s);
                             break;
                         }
@@ -8106,7 +8090,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                         gen_exception_return(s, tmp);
                         break;
                     case 6: /* mrs cpsr.  */
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         if (IS_M(env)) {
                             addr = tcg_const_i32(insn & 0xff);
                             gen_helper_v7m_mrs(tmp, cpu_env, addr);
@@ -8158,7 +8142,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     imm = insn & 0x1f;
                     shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
                     if (rn == 15) {
-                        tmp = new_tmp();
+                        tmp = tcg_temp_new_i32();
                         tcg_gen_movi_i32(tmp, 0);
                     } else {
                         tmp = load_reg(s, rn);
@@ -8185,7 +8169,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                         if (imm != 32) {
                             tmp2 = load_reg(s, rd);
                             gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
-                            dead_tmp(tmp2);
+                            tcg_temp_free_i32(tmp2);
                         }
                         break;
                     case 7:
@@ -8228,7 +8212,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                             tcg_gen_ori_i32(tmp, tmp, imm << 16);
                         } else {
                             /* movw */
-                            tmp = new_tmp();
+                            tmp = tcg_temp_new_i32();
                             tcg_gen_movi_i32(tmp, imm);
                         }
                     } else {
@@ -8239,7 +8223,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                                 offset -= imm;
                             else
                                 offset += imm;
-                            tmp = new_tmp();
+                            tmp = tcg_temp_new_i32();
                             tcg_gen_movi_i32(tmp, offset);
                         } else {
                             tmp = load_reg(s, rn);
@@ -8278,11 +8262,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     shifter_out = 1;
                     break;
                 }
-                tmp2 = new_tmp();
+                tmp2 = tcg_temp_new_i32();
                 tcg_gen_movi_i32(tmp2, imm);
                 rn = (insn >> 16) & 0xf;
                 if (rn == 15) {
-                    tmp = new_tmp();
+                    tmp = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp, 0);
                 } else {
                     tmp = load_reg(s, rn);
@@ -8291,12 +8275,12 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
                                        shifter_out, tmp, tmp2))
                     goto illegal_op;
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 rd = (insn >> 8) & 0xf;
                 if (rd != 15) {
                     store_reg(s, rd, tmp);
                 } else {
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                 }
             }
         }
@@ -8349,7 +8333,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
         }
         user = IS_USER(s);
         if (rn == 15) {
-            addr = new_tmp();
+            addr = tcg_temp_new_i32();
             /* PC relative.  */
             /* s->pc has already been incremented by 4.  */
             imm = s->pc & 0xfffffffc;
@@ -8375,7 +8359,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                     if (shift)
                         tcg_gen_shli_i32(tmp, tmp, shift);
                     tcg_gen_add_i32(addr, addr, tmp);
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
                     break;
                 case 4: /* Negative offset.  */
                     tcg_gen_addi_i32(addr, addr, -imm);
@@ -8433,7 +8417,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
         if (writeback) {
             store_reg(s, rn, addr);
         } else {
-            dead_tmp(addr);
+            tcg_temp_free_i32(addr);
         }
         }
         break;
@@ -8477,7 +8461,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, rn);
             if (insn & (1 << 10)) {
                 /* immediate */
-                tmp2 = new_tmp();
+                tmp2 = tcg_temp_new_i32();
                 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
             } else {
                 /* reg */
@@ -8495,7 +8479,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 else
                     gen_helper_add_cc(tmp, tmp, tmp2);
             }
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp2);
             store_reg(s, rd, tmp);
         } else {
             /* shift immediate */
@@ -8513,27 +8497,27 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         op = (insn >> 11) & 3;
         rd = (insn >> 8) & 0x7;
         if (op == 0) { /* mov */
-            tmp = new_tmp();
+            tmp = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp, insn & 0xff);
             if (!s->condexec_mask)
                 gen_logic_CC(tmp);
             store_reg(s, rd, tmp);
         } else {
             tmp = load_reg(s, rd);
-            tmp2 = new_tmp();
+            tmp2 = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp2, insn & 0xff);
             switch (op) {
             case 1: /* cmp */
                 gen_helper_sub_cc(tmp, tmp, tmp2);
-                dead_tmp(tmp);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp);
+                tcg_temp_free_i32(tmp2);
                 break;
             case 2: /* add */
                 if (s->condexec_mask)
                     tcg_gen_add_i32(tmp, tmp, tmp2);
                 else
                     gen_helper_add_cc(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 store_reg(s, rd, tmp);
                 break;
             case 3: /* sub */
@@ -8541,7 +8525,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
                     tcg_gen_sub_i32(tmp, tmp, tmp2);
                 else
                     gen_helper_sub_cc(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 store_reg(s, rd, tmp);
                 break;
             }
@@ -8553,10 +8537,10 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             /* load pc-relative.  Bit 1 of PC is ignored.  */
             val = s->pc + 2 + ((insn & 0xff) * 4);
             val &= ~(uint32_t)2;
-            addr = new_tmp();
+            addr = tcg_temp_new_i32();
             tcg_gen_movi_i32(addr, val);
             tmp = gen_ld32(addr, IS_USER(s));
-            dead_tmp(addr);
+            tcg_temp_free_i32(addr);
             store_reg(s, rd, tmp);
             break;
         }
@@ -8570,15 +8554,15 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 tmp = load_reg(s, rd);
                 tmp2 = load_reg(s, rm);
                 tcg_gen_add_i32(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
                 store_reg(s, rd, tmp);
                 break;
             case 1: /* cmp */
                 tmp = load_reg(s, rd);
                 tmp2 = load_reg(s, rm);
                 gen_helper_sub_cc(tmp, tmp, tmp2);
-                dead_tmp(tmp2);
-                dead_tmp(tmp);
+                tcg_temp_free_i32(tmp2);
+                tcg_temp_free_i32(tmp);
                 break;
             case 2: /* mov/cpy */
                 tmp = load_reg(s, rm);
@@ -8588,7 +8572,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 tmp = load_reg(s, rm);
                 if (insn & (1 << 7)) {
                     val = (uint32_t)s->pc | 1;
-                    tmp2 = new_tmp();
+                    tmp2 = tcg_temp_new_i32();
                     tcg_gen_movi_i32(tmp2, val);
                     store_reg(s, 14, tmp2);
                 }
@@ -8613,7 +8597,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         }
 
         if (op == 9) { /* neg */
-            tmp = new_tmp();
+            tmp = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp, 0);
         } else if (op != 0xf) { /* mvn doesn't read its first operand */
             tmp = load_reg(s, rd);
@@ -8724,14 +8708,14 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             if (val) {
                 store_reg(s, rm, tmp2);
                 if (op != 0xf)
-                    dead_tmp(tmp);
+                    tcg_temp_free_i32(tmp);
             } else {
                 store_reg(s, rd, tmp);
-                dead_tmp(tmp2);
+                tcg_temp_free_i32(tmp2);
             }
         } else {
-            dead_tmp(tmp);
-            dead_tmp(tmp2);
+            tcg_temp_free_i32(tmp);
+            tcg_temp_free_i32(tmp2);
         }
         break;
 
@@ -8744,7 +8728,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         addr = load_reg(s, rn);
         tmp = load_reg(s, rm);
         tcg_gen_add_i32(addr, addr, tmp);
-        dead_tmp(tmp);
+        tcg_temp_free_i32(tmp);
 
         if (op < 3) /* store */
             tmp = load_reg(s, rd);
@@ -8777,7 +8761,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         }
         if (op >= 3) /* load */
             store_reg(s, rd, tmp);
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         break;
 
     case 6:
@@ -8797,7 +8781,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, rd);
             gen_st32(tmp, addr, IS_USER(s));
         }
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         break;
 
     case 7:
@@ -8817,7 +8801,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, rd);
             gen_st8(tmp, addr, IS_USER(s));
         }
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         break;
 
     case 8:
@@ -8837,7 +8821,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, rd);
             gen_st16(tmp, addr, IS_USER(s));
         }
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         break;
 
     case 9:
@@ -8856,7 +8840,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, rd);
             gen_st32(tmp, addr, IS_USER(s));
         }
-        dead_tmp(addr);
+        tcg_temp_free_i32(addr);
         break;
 
     case 10:
@@ -8867,7 +8851,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             tmp = load_reg(s, 13);
         } else {
             /* PC. bit 1 is ignored.  */
-            tmp = new_tmp();
+            tmp = tcg_temp_new_i32();
             tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
         }
         val = (insn & 0xff) * 4;
@@ -8964,7 +8948,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
             else
                 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
-            dead_tmp(tmp);
+            tcg_temp_free_i32(tmp);
             offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
             val = (uint32_t)s->pc + 2;
             val += offset;
@@ -9057,7 +9041,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         if ((insn & (1 << rn)) == 0) {
             store_reg(s, rn, addr);
         } else {
-            dead_tmp(addr);
+            tcg_temp_free_i32(addr);
         }
         break;
 
@@ -9129,8 +9113,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     int max_insns;
 
     /* generate intermediate code */
-    num_temps = 0;
-
     pc_start = tb->pc;
 
     dc->tb = tb;
@@ -9202,7 +9184,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
        complications trying to do it at the end of the block.  */
     if (dc->condexec_mask || dc->condexec_cond)
       {
-        TCGv tmp = new_tmp();
+        TCGv tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, 0);
         store_cpu_field(tmp, condexec_bits);
       }
@@ -9271,10 +9253,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         } else {
             disas_arm_insn(env, dc);
         }
-        if (num_temps) {
-            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
-            num_temps = 0;
-        }
 
         if (dc->condjmp && !dc->is_jmp) {
             gen_set_label(dc->condlabel);
commit 27bfd83c336283d1f7a5345ee386c4cd7b80db61
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Mar 6 21:39:53 2011 +0000

    tcg: Add support for debugging leakage of temporaries
    
    Add support (if CONFIG_DEBUG_TCG is defined) for debugging leakage
    of temporary variables. Generally any temporaries created by
    a target while it is translating an instruction should be freed
    by the end of that instruction; otherwise carefully crafted
    guest code could cause TCG to run out of temporaries and assert.
    By calling tcg_check_temp_count() after each instruction we can
    check that we are not leaking temporaries in this way.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 5dd6a2c..8748c05 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -450,6 +450,10 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local)
             s->nb_temps++;
         }
     }
+
+#if defined(CONFIG_DEBUG_TCG)
+    s->temps_in_use++;
+#endif
     return idx;
 }
 
@@ -475,6 +479,13 @@ static inline void tcg_temp_free_internal(int idx)
     TCGTemp *ts;
     int k;
 
+#if defined(CONFIG_DEBUG_TCG)
+    s->temps_in_use--;
+    if (s->temps_in_use < 0) {
+        fprintf(stderr, "More temporaries freed than allocated!\n");
+    }
+#endif
+
     assert(idx >= s->nb_globals && idx < s->nb_temps);
     ts = &s->temps[idx];
     assert(ts->temp_allocated != 0);
@@ -528,6 +539,27 @@ TCGv_i64 tcg_const_local_i64(int64_t val)
     return t0;
 }
 
+#if defined(CONFIG_DEBUG_TCG)
+void tcg_clear_temp_count(void)
+{
+    TCGContext *s = &tcg_ctx;
+    s->temps_in_use = 0;
+}
+
+int tcg_check_temp_count(void)
+{
+    TCGContext *s = &tcg_ctx;
+    if (s->temps_in_use) {
+        /* Clear the count so that we don't give another
+         * warning immediately next time around.
+         */
+        s->temps_in_use = 0;
+        return 1;
+    }
+    return 0;
+}
+#endif
+
 void tcg_register_helper(void *func, const char *name)
 {
     TCGContext *s = &tcg_ctx;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index e1afde2..3fab8d6 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -323,6 +323,10 @@ struct TCGContext {
     int64_t restore_count;
     int64_t restore_time;
 #endif
+
+#ifdef CONFIG_DEBUG_TCG
+    int temps_in_use;
+#endif
 };
 
 extern TCGContext tcg_ctx;
@@ -392,6 +396,19 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void)
 void tcg_temp_free_i64(TCGv_i64 arg);
 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg);
 
+#if defined(CONFIG_DEBUG_TCG)
+/* If you call tcg_clear_temp_count() at the start of a section of
+ * code which is not supposed to leak any TCG temporaries, then
+ * calling tcg_check_temp_count() at the end of the section will
+ * return 1 if the section did in fact leak a temporary.
+ */
+void tcg_clear_temp_count(void);
+int tcg_check_temp_count(void);
+#else
+#define tcg_clear_temp_count() do { } while (0)
+#define tcg_check_temp_count() 0
+#endif
+
 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf);
 
 #define TCG_CT_ALIAS  0x80
commit 6ed221b637713aec903136e3061e714fa4809bdd
Author: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
Date:   Sat Mar 5 13:51:45 2011 +0100

    target-arm: Integrate secondary CPU reset in arm_boot
    
    Integrate secondary CPU reset into arm_boot, removing it from realview.c.
    On non-Linux systems secondary CPUs start with the same entry as the boot
    CPU.
    
    Signed-off-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 620550b..41e99d1 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -175,7 +175,7 @@ static void set_kernel_args_old(struct arm_boot_info *info,
     }
 }
 
-static void main_cpu_reset(void *opaque)
+static void do_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
     struct arm_boot_info *info = env->boot_info;
@@ -187,16 +187,20 @@ static void main_cpu_reset(void *opaque)
             env->regs[15] = info->entry & 0xfffffffe;
             env->thumb = info->entry & 1;
         } else {
-            env->regs[15] = info->loader_start;
-            if (old_param) {
-                set_kernel_args_old(info, info->initrd_size,
+            if (env == first_cpu) {
+                env->regs[15] = info->loader_start;
+                if (old_param) {
+                    set_kernel_args_old(info, info->initrd_size,
+                                        info->loader_start);
+                } else {
+                    set_kernel_args(info, info->initrd_size,
                                     info->loader_start);
+                }
             } else {
-                set_kernel_args(info, info->initrd_size, info->loader_start);
+                env->regs[15] = info->smp_loader_start;
             }
         }
     }
-    /* TODO:  Reset secondary CPUs.  */
 }
 
 void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
@@ -217,7 +221,6 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
 
     if (info->nb_cpus == 0)
         info->nb_cpus = 1;
-    env->boot_info = info;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -279,5 +282,9 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         info->initrd_size = initrd_size;
     }
     info->is_linux = is_linux;
-    qemu_register_reset(main_cpu_reset, env);
+
+    for (; env; env = env->next_cpu) {
+        env->boot_info = info;
+        qemu_register_reset(do_cpu_reset, env);
+    }
 }
diff --git a/hw/realview.c b/hw/realview.c
index 466b210..a67861e 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -104,17 +104,6 @@ static struct arm_boot_info realview_binfo = {
     .smp_loader_start = SMP_BOOT_ADDR,
 };
 
-static void secondary_cpu_reset(void *opaque)
-{
-  CPUState *env = opaque;
-
-  cpu_reset(env);
-  /* Set entry point for secondary CPUs.  This assumes we're using
-     the init code from arm_boot.c.  Real hardware resets all CPUs
-     the same.  */
-  env->regs[15] = SMP_BOOT_ADDR;
-}
-
 /* The following two lists must be consistent.  */
 enum realview_board_type {
     BOARD_EB,
@@ -177,9 +166,6 @@ static void realview_init(ram_addr_t ram_size,
         }
         irqp = arm_pic_init_cpu(env);
         cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-        if (n > 0) {
-            qemu_register_reset(secondary_cpu_reset, env);
-        }
     }
     if (arm_feature(env, ARM_FEATURE_V7)) {
         if (is_mpcore) {
commit f8bf860605e7f43a0803c4f099ac67aa545bbb68
Author: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
Date:   Sat Mar 5 13:51:44 2011 +0100

    target-arm: Implement cp15 VA->PA translation
    
    Implement VA->PA translations by cp15-c7 that went through unchanged
    previously.
    
    Signed-off-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c9febfa..1ae7982 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -126,6 +126,7 @@ typedef struct CPUARMState {
         uint32_t c6_region[8]; /* MPU base/size registers.  */
         uint32_t c6_insn; /* Fault address registers.  */
         uint32_t c6_data;
+        uint32_t c7_par;  /* Translation result. */
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
         uint32_t c13_fcse; /* FCSE PID.  */
@@ -428,7 +429,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 2
+#define CPU_SAVE_VERSION 3
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1852352..d360121 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1456,8 +1456,49 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
     case 7: /* Cache control.  */
         env->cp15.c15_i_max = 0x000;
         env->cp15.c15_i_min = 0xff0;
-        /* No cache, so nothing to do.  */
-        /* ??? MPCore has VA to PA translation functions.  */
+        if (op1 != 0) {
+            goto bad_reg;
+        }
+        /* No cache, so nothing to do except VA->PA translations. */
+        if (arm_feature(env, ARM_FEATURE_V6K)) {
+            switch (crm) {
+            case 4:
+                if (arm_feature(env, ARM_FEATURE_V7)) {
+                    env->cp15.c7_par = val & 0xfffff6ff;
+                } else {
+                    env->cp15.c7_par = val & 0xfffff1ff;
+                }
+                break;
+            case 8: {
+                uint32_t phys_addr;
+                target_ulong page_size;
+                int prot;
+                int ret, is_user = op2 & 2;
+                int access_type = op2 & 1;
+
+                if (op2 & 4) {
+                    /* Other states are only available with TrustZone */
+                    goto bad_reg;
+                }
+                ret = get_phys_addr(env, val, access_type, is_user,
+                                    &phys_addr, &prot, &page_size);
+                if (ret == 0) {
+                    /* We do not set any attribute bits in the PAR */
+                    if (page_size == (1 << 24)
+                        && arm_feature(env, ARM_FEATURE_V7)) {
+                        env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+                    } else {
+                        env->cp15.c7_par = phys_addr & 0xfffff000;
+                    }
+                } else {
+                    env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
+                                       ((ret & (12 << 1)) >> 6) |
+                                       ((ret & 0xf) << 1) | 1;
+                }
+                break;
+            }
+            }
+        }
         break;
     case 8: /* MMU TLB control.  */
         switch (op2) {
@@ -1789,6 +1830,9 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
 	    }
         }
     case 7: /* Cache control.  */
+        if (crm == 4 && op1 == 0 && op2 == 0) {
+            return env->cp15.c7_par;
+        }
         /* FIXME: Should only clear Z flag if destination is r15.  */
         env->ZF = 0;
         return 0;
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 3925d3a..a18b7dc 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -41,6 +41,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     }
     qemu_put_be32(f, env->cp15.c6_insn);
     qemu_put_be32(f, env->cp15.c6_data);
+    qemu_put_be32(f, env->cp15.c7_par);
     qemu_put_be32(f, env->cp15.c9_insn);
     qemu_put_be32(f, env->cp15.c9_data);
     qemu_put_be32(f, env->cp15.c13_fcse);
@@ -148,6 +149,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     }
     env->cp15.c6_insn = qemu_get_be32(f);
     env->cp15.c6_data = qemu_get_be32(f);
+    env->cp15.c7_par = qemu_get_be32(f);
     env->cp15.c9_insn = qemu_get_be32(f);
     env->cp15.c9_data = qemu_get_be32(f);
     env->cp15.c13_fcse = qemu_get_be32(f);
commit fa25014441dc5fafb8f00eeff44172f073bf379d
Author: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
Date:   Sat Mar 5 13:51:42 2011 +0100

    target-arm: Fix soft interrupt in GIC distributor
    
    Fix selection of target list filter mode.
    
    Signed-off-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index e6b1953..0e934ec 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -549,10 +549,10 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
             mask = (value >> 16) & ALL_CPU_MASK;
             break;
         case 1:
-            mask = 1 << cpu;
+            mask = ALL_CPU_MASK ^ (1 << cpu);
             break;
         case 2:
-            mask = ALL_CPU_MASK ^ (1 << cpu);
+            mask = 1 << cpu;
             break;
         default:
             DPRINTF("Bad Soft Int target filter\n");
commit 29501f1b9e6b1ee9d5d4761a452116321be5ae95
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Mar 6 20:32:09 2011 +0000

    target-arm: Set carry flag correctly for Thumb2 ORNS
    
    The code for Thumb2 ORNS (or negated and set flags) was trashing
    a TCG input register which was needed later for use in calculating
    flags, with the effect that the carry flag was always set with
    the wrong sense. Fix this by using the TCG orc op instead of
    separate not and or ops.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5be504c..b08b636 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7351,8 +7351,7 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG
         logic_cc = conds;
         break;
     case 3: /* orn */
-        tcg_gen_not_i32(t1, t1);
-        tcg_gen_or_i32(t0, t0, t1);
+        tcg_gen_orc_i32(t0, t0, t1);
         logic_cc = conds;
         break;
     case 4: /* eor */
commit f66a99d7526782495931bb1ef22f0a6c623c0ff0
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Sun Mar 6 15:48:13 2011 +0100

    ioport: Improve error output
    
    When failing due to conflicting I/O port registrations,
    include the offending I/O port address in the message.
    
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/ioport.c b/ioport.c
index aa4188a..2e971fa 100644
--- a/ioport.c
+++ b/ioport.c
@@ -149,7 +149,8 @@ int register_ioport_read(pio_addr_t start, int length, int size,
     for(i = start; i < start + length; i += size) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
-            hw_error("register_ioport_read: invalid opaque");
+            hw_error("register_ioport_read: invalid opaque for address 0x%x",
+                     i);
         ioport_opaque[i] = opaque;
     }
     return 0;
@@ -168,7 +169,8 @@ int register_ioport_write(pio_addr_t start, int length, int size,
     for(i = start; i < start + length; i += size) {
         ioport_write_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
-            hw_error("register_ioport_write: invalid opaque");
+            hw_error("register_ioport_write: invalid opaque for address 0x%x",
+                     i);
         ioport_opaque[i] = opaque;
     }
     return 0;
commit e323c93edf3abb67c37b8e08b78da4835880f12e
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Feb 17 13:26:05 2011 +0100

    tracetool: Add optional argument to specify dtrace probe names
    
    Optional feature allowing a user to generate the probe list to match
    the name of the binary, in case they wish to install qemu under a
    different name than qemu-{system,user},<arch>
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Stefan Hajnoczi <stefaha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/scripts/tracetool b/scripts/tracetool
index e046683..412f695 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -30,9 +30,11 @@ Output formats:
   --stap Generate .stp file (DTrace with SystemTAP only)
 
 Options:
-  --binary      [path]  Full path to QEMU binary
-  --target-arch [arch]  QEMU emulator target arch
-  --target-type [type]  QEMU emulator target type ('system' or 'user')
+  --binary       [path]    Full path to QEMU binary
+  --target-arch  [arch]    QEMU emulator target arch
+  --target-type  [type]    QEMU emulator target type ('system' or 'user')
+  --probe-prefix [prefix]  Prefix for dtrace probe names
+                           (default: qemu-\$targettype-\$targetarch)
 
 EOF
     exit 1
@@ -472,7 +474,7 @@ linetostap_dtrace()
 
     # Define prototype for probe arguments
     cat <<EOF
-probe qemu.$targettype.$targetarch.$name = process("$binary").mark("$name")
+probe $probeprefix.$name = process("$binary").mark("$name")
 {
 EOF
 
@@ -574,14 +576,17 @@ tracetostap()
        echo "--binary is required for SystemTAP tapset generator"
        exit 1
     fi
-    if [ -z "$targettype" ]; then
+    if [ -z "$probeprefix" -a -z "$targettype" ]; then
        echo "--target-type is required for SystemTAP tapset generator"
        exit 1
     fi
-    if [ -z "$targetarch" ]; then
+    if [ -z "$probeprefix" -a -z "$targetarch" ]; then
        echo "--target-arch is required for SystemTAP tapset generator"
        exit 1
     fi
+    if [ -z "$probeprefix" ]; then
+	probeprefix="qemu.$targettype.$targetarch";
+    fi
     echo "/* This file is autogenerated by tracetool, do not edit. */"
     convert stap
 }
@@ -592,6 +597,7 @@ output=
 binary=
 targettype=
 targetarch=
+probeprefix=
 
 
 until [ -z "$1" ]
@@ -602,6 +608,7 @@ do
     "--binary") shift ; binary="$1" ;;
     "--target-arch") shift ; targetarch="$1" ;;
     "--target-type") shift ; targettype="$1" ;;
+    "--probe-prefix") shift ; probeprefix="$1" ;;
 
     "-h" | "-c" | "-d") output="${1#-}" ;;
     "--stap") output="${1#--}" ;;
commit 8387da81975a1f5d310d5f3008514c419b3e82de
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 1 17:35:19 2011 +0000

    target-arm: Handle VMOV between two core and VFP single regs
    
    Fix two bugs in the translation of the instructions VMOV sa,sb,rx,ry and
    VMOV rx,ry,sa,sb (which copy between a pair of ARM core registers and a
    pair of VFP single precision registers):
    
     * An incorrect condition meant these instruction patterns were being
       treated as load/store multiple, which resulted in the generation
       of bad code and a runtime segfault
     * The order of the core register pair was reversed so the values would
       go to the wrong registers
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index baa1256..5be504c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3257,7 +3257,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
         break;
     case 0xc:
     case 0xd:
-        if (dp && (insn & 0x03e00000) == 0x00400000) {
+        if ((insn & 0x03e00000) == 0x00400000) {
             /* two-register transfer */
             rn = (insn >> 16) & 0xf;
             rd = (insn >> 12) & 0xf;
@@ -3279,10 +3279,10 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 } else {
                     gen_mov_F0_vreg(0, rm);
                     tmp = gen_vfp_mrs();
-                    store_reg(s, rn, tmp);
+                    store_reg(s, rd, tmp);
                     gen_mov_F0_vreg(0, rm + 1);
                     tmp = gen_vfp_mrs();
-                    store_reg(s, rd, tmp);
+                    store_reg(s, rn, tmp);
                 }
             } else {
                 /* arm->vfp */
@@ -3294,10 +3294,10 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     gen_vfp_msr(tmp);
                     gen_mov_vreg_F0(0, rm * 2 + 1);
                 } else {
-                    tmp = load_reg(s, rn);
+                    tmp = load_reg(s, rd);
                     gen_vfp_msr(tmp);
                     gen_mov_vreg_F0(0, rm);
-                    tmp = load_reg(s, rd);
+                    tmp = load_reg(s, rn);
                     gen_vfp_msr(tmp);
                     gen_mov_vreg_F0(0, rm + 1);
                 }
commit e095e2f3b47ced1ced72f3f2c72260e55f39903b
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Feb 27 20:23:30 2011 +0100

    w32: Add support for curses
    
    MinGW optionally includes pdcurses, so add support for it.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 3036faf..ef51a58 100755
--- a/configure
+++ b/configure
@@ -1561,7 +1561,11 @@ fi
 
 ##########################################
 # curses probe
-curses_list="-lncurses -lcurses"
+if test "$mingw32" = "yes" ; then
+    curses_list="-lpdcurses"
+else
+    curses_list="-lncurses -lcurses"
+fi
 
 if test "$curses" != "no" ; then
   curses_found=no
commit cc68890166c2c1c5003e3eeb8535e1872e239a95
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 25 15:04:12 2011 +0000

    target-arm: Don't decode old cp15 WFI instructions on v7 cores
    
    In v7 of the ARM architecture, WFI (wait for interrupt) is a first-class
    instruction, but in previous versions this functionality was provided
    via a cp15 coprocessor register. Add correct feature checks to the
    decoding of the cp15 WFI instructions so that they behave correctly
    for newer cores. In particular, the old 0,c7,c8,2 encoding used on
    ARM940 has been reused for VA-to-PA translation in v6 and v7.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index dbd958b..baa1256 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2538,13 +2538,38 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
     if (IS_USER(s) && !cp15_user_ok(insn)) {
         return 1;
     }
-    if ((insn & 0x0fff0fff) == 0x0e070f90
-        || (insn & 0x0fff0fff) == 0x0e070f58) {
-        /* Wait for interrupt.  */
-        gen_set_pc_im(s->pc);
-        s->is_jmp = DISAS_WFI;
+
+    /* Pre-v7 versions of the architecture implemented WFI via coprocessor
+     * instructions rather than a separate instruction.
+     */
+    if ((insn & 0x0fff0fff) == 0x0e070f90) {
+        /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
+         * In v7, this must NOP.
+         */
+        if (!arm_feature(env, ARM_FEATURE_V7)) {
+            /* Wait for interrupt.  */
+            gen_set_pc_im(s->pc);
+            s->is_jmp = DISAS_WFI;
+        }
         return 0;
     }
+
+    if ((insn & 0x0fff0fff) == 0x0e070f58) {
+        /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
+         * so this is slightly over-broad.
+         */
+        if (!arm_feature(env, ARM_FEATURE_V6)) {
+            /* Wait for interrupt.  */
+            gen_set_pc_im(s->pc);
+            s->is_jmp = DISAS_WFI;
+            return 0;
+        }
+        /* Otherwise fall through to handle via helper function.
+         * In particular, on v7 and some v6 cores this is one of
+         * the VA-PA registers.
+         */
+    }
+
     rd = (insn >> 12) & 0xf;
 
     if (cp15_tls_load_store(env, s, insn, rd))
commit 96c94b298f99d6edf4e49d03cc8458f5b6e9d5f0
Author: Jason Wang <jasowang at redhat.com>
Date:   Fri Feb 25 16:11:27 2011 +0800

    net: Add the missing option declaration of "vhostforce"
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index 54e8992..ddcca97 100644
--- a/net.c
+++ b/net.c
@@ -968,7 +968,11 @@ static const struct {
                 .name = "vhostfd",
                 .type = QEMU_OPT_STRING,
                 .help = "file descriptor of an already opened vhost net device",
-            },
+            }, {
+                .name = "vhostforce",
+                .type = QEMU_OPT_BOOL,
+                .help = "force vhost on for non-MSIX virtio guests",
+        },
 #endif /* _WIN32 */
             { /* end of list */ }
         },
commit 05a7fcd08189300fc89d841c2e4c522226afece7
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Feb 24 15:17:16 2011 +0100

    gt64xxx: remove savevm support
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 923073b..c66188f 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1080,25 +1080,6 @@ static void gt64120_reset(void *opaque)
     gt64120_pci_mapping(s);
 }
 
-static void gt64120_save(QEMUFile* f, void *opaque)
-{
-    PCIDevice *d = opaque;
-    pci_device_save(d, f);
-}
-
-static int gt64120_load(QEMUFile* f, void *opaque, int version_id)
-{
-    PCIDevice *d = opaque;
-    int ret;
-
-    if (version_id != 1)
-        return -EINVAL;
-    ret = pci_device_load(d, f);
-    if (ret < 0)
-        return ret;
-    return 0;
-}
-
 PCIBus *gt64120_register(qemu_irq *pic)
 {
     SysBusDevice *s;
@@ -1131,8 +1112,6 @@ static int gt64120_init(SysBusDevice *dev)
        does not fully work. */
     isa_mem_base = 0x10000000;
     qemu_register_reset(gt64120_reset, s);
-    register_savevm(&dev->qdev, "GT64120 PCI Bus", 0, 1,
-                    gt64120_save, gt64120_load, &s->pci);
     return 0;
 }
 
commit 9023f7b2c8af154744fe3ed3412be00d0424e874
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Feb 24 15:17:15 2011 +0100

    vmstate: remove uninorth savevm code
    
    It was migrating the wrong structures, no way it would work
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 5f15058..c57c0a1 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -63,23 +63,6 @@ static void pci_unin_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[unin_irq_line[irq_num]], level);
 }
 
-static void pci_unin_save(QEMUFile* f, void *opaque)
-{
-    PCIDevice *d = opaque;
-
-    pci_device_save(d, f);
-}
-
-static int pci_unin_load(QEMUFile* f, void *opaque, int version_id)
-{
-    PCIDevice *d = opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    return pci_device_load(d, f);
-}
-
 static void pci_unin_reset(void *opaque)
 {
 }
@@ -158,8 +141,6 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm(&dev->qdev, "uninorth", 0, 1,
-                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
     return 0;
 }
@@ -181,8 +162,6 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm(&dev->qdev, "uninorth", 0, 1,
-                    pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
 
     return 0;
commit 532847e427e0c784216c8be943f7cdeec6c307d0
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Feb 24 15:17:14 2011 +0100

    vmstate: remove grackle_pci savevm code
    
    It was migrating the wrong structures, no way it would work
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index bd3d6b0..d35701f 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -57,23 +57,6 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[irq_num + 0x15], level);
 }
 
-static void pci_grackle_save(QEMUFile* f, void *opaque)
-{
-    PCIDevice *d = opaque;
-
-    pci_device_save(d, f);
-}
-
-static int pci_grackle_load(QEMUFile* f, void *opaque, int version_id)
-{
-    PCIDevice *d = opaque;
-
-    if (version_id != 1)
-        return -EINVAL;
-
-    return pci_device_load(d, f);
-}
-
 static void pci_grackle_reset(void *opaque)
 {
 }
@@ -115,8 +98,6 @@ static int pci_grackle_init_device(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
-    register_savevm(&dev->qdev, "grackle", 0, 1, pci_grackle_save,
-                    pci_grackle_load, &s->host_state);
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     return 0;
 }
commit 85bb6d36b055e64778086b951ea282b383014274
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Feb 24 12:22:10 2011 +0100

    net: remove parse_host_src_port() function
    
    It was deprecated, and it has no users.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index 436c24c..54e8992 100644
--- a/net.c
+++ b/net.c
@@ -94,47 +94,6 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
     return 0;
 }
 
-int parse_host_src_port(struct sockaddr_in *haddr,
-                        struct sockaddr_in *saddr,
-                        const char *input_str)
-{
-    char *str = qemu_strdup(input_str);
-    char *host_str = str;
-    char *src_str;
-    const char *src_str2;
-    char *ptr;
-
-    /*
-     * Chop off any extra arguments at the end of the string which
-     * would start with a comma, then fill in the src port information
-     * if it was provided else use the "any address" and "any port".
-     */
-    if ((ptr = strchr(str,',')))
-        *ptr = '\0';
-
-    if ((src_str = strchr(input_str,'@'))) {
-        *src_str = '\0';
-        src_str++;
-    }
-
-    if (parse_host_port(haddr, host_str) < 0)
-        goto fail;
-
-    src_str2 = src_str;
-    if (!src_str || *src_str == '\0')
-        src_str2 = ":0";
-
-    if (parse_host_port(saddr, src_str2) < 0)
-        goto fail;
-
-    free(str);
-    return(0);
-
-fail:
-    free(str);
-    return -1;
-}
-
 int parse_host_port(struct sockaddr_in *saddr, const char *str)
 {
     char buf[512];
diff --git a/qemu_socket.h b/qemu_socket.h
index 897a8ae..180e4db 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -54,9 +54,6 @@ int unix_connect(const char *path);
 
 /* Old, ipv4 only bits.  Don't use for new code. */
 int parse_host_port(struct sockaddr_in *saddr, const char *str);
-int parse_host_src_port(struct sockaddr_in *haddr,
-                        struct sockaddr_in *saddr,
-                        const char *str);
 int socket_init(void);
 
 #endif /* QEMU_SOCKET_H */
commit 0d2e91c17829729812bf5d22d20dd0f5d2554ec2
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Mar 6 20:02:40 2011 +0100

    hw/sd.c: fix sd_set_cb() crash when bdrv == NULL
    
    sd_set_cb() calls bdrv_is_read_only() and bdrv_is_inserted() even if
    no block driver is associated with the card reader.
    
    This patch fixes the issues by not setting the irq in this case, this
    fixes ARM versatile crash.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/sd.c b/hw/sd.c
index 5e29752..f44a970 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -460,8 +460,8 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
 {
     sd->readonly_cb = readonly;
     sd->inserted_cb = insert;
-    qemu_set_irq(readonly, bdrv_is_read_only(sd->bdrv));
-    qemu_set_irq(insert, bdrv_is_inserted(sd->bdrv));
+    qemu_set_irq(readonly, sd->bdrv ? bdrv_is_read_only(sd->bdrv) : 0);
+    qemu_set_irq(insert, sd->bdrv ? bdrv_is_inserted(sd->bdrv) : 0);
 }
 
 static void sd_erase(SDState *sd)
commit ce0536616d338e3ee56288fa8e7aee1ea75e92d4
Author: Benjamin Poirier <benjamin.poirier at gmail.com>
Date:   Wed Feb 23 19:57:21 2011 -0500

    net: Use iov helper functions
    
    Signed-off-by: Benjamin Poirier <benjamin.poirier at gmail.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index 72ac4cf..436c24c 100644
--- a/net.c
+++ b/net.c
@@ -36,6 +36,7 @@
 #include "qemu-common.h"
 #include "qemu_socket.h"
 #include "hw/qdev.h"
+#include "iov.h"
 
 static QTAILQ_HEAD(, VLANState) vlans;
 static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
@@ -572,30 +573,13 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov,
                                int iovcnt)
 {
     uint8_t buffer[4096];
-    size_t offset = 0;
-    int i;
-
-    for (i = 0; i < iovcnt; i++) {
-        size_t len;
+    size_t offset;
 
-        len = MIN(sizeof(buffer) - offset, iov[i].iov_len);
-        memcpy(buffer + offset, iov[i].iov_base, len);
-        offset += len;
-    }
+    offset = iov_to_buf(iov, iovcnt, buffer, 0, sizeof(buffer));
 
     return vc->info->receive(vc, buffer, offset);
 }
 
-static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
-{
-    size_t offset = 0;
-    int i;
-
-    for (i = 0; i < iovcnt; i++)
-        offset += iov[i].iov_len;
-    return offset;
-}
-
 static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
                                        unsigned flags,
                                        const struct iovec *iov,
@@ -605,7 +589,7 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
     VLANClientState *vc = opaque;
 
     if (vc->link_down) {
-        return calc_iov_length(iov, iovcnt);
+        return iov_size(iov, iovcnt);
     }
 
     if (vc->info->receive_iov) {
@@ -633,7 +617,7 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
         }
 
         if (vc->link_down) {
-            ret = calc_iov_length(iov, iovcnt);
+            ret = iov_size(iov, iovcnt);
             continue;
         }
 
@@ -658,7 +642,7 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender,
     NetQueue *queue;
 
     if (sender->link_down || (!sender->peer && !sender->vlan)) {
-        return calc_iov_length(iov, iovcnt);
+        return iov_size(iov, iovcnt);
     }
 
     if (sender->peer) {
commit b48c20f723cba21ffe62fb99094d2fa36739b0cc
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Feb 23 14:00:21 2011 +0000

    docs: Update stderr and simple backend, add systemtap backend
    
    The following additions to the tracing documentation are included:
    
    1. Move "stderr" backend documentation to top-level and out of "simple"
       backend.  Include hints on when this backend is useful.
    
    2. Document the "simple" backend thread-safety limitation.
    
    3. Document the "dtrace" backend for SystemTap.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 21183f9..a6cc56f 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -126,6 +126,14 @@ The "nop" backend generates empty trace event functions so that the compiler
 can optimize out trace events completely.  This is the default and imposes no
 performance penalty.
 
+=== Stderr ===
+
+The "stderr" backend sends trace events directly to standard error.  This
+effectively turns trace events into debug printfs.
+
+This is the simplest backend and can be used together with existing code that
+uses DPRINTF().
+
 === Simpletrace ===
 
 The "simple" backend supports common use cases and comes as part of the QEMU
@@ -133,10 +141,10 @@ source tree.  It may not be as powerful as platform-specific or third-party
 trace backends but it is portable.  This is the recommended trace backend
 unless you have specific needs for more advanced backends.
 
-=== Stderr ===
-
-The "stderr" backend sends trace events directly to standard error output
-during emulation.
+Warning: the "simple" backend is not thread-safe so only enable trace events
+that are executed while the global mutex is held.  Much of QEMU meets this
+requirement but some utility functions like qemu_malloc() or thread-related
+code cannot be safely traced using the "simple" backend.
 
 ==== Monitor commands ====
 
@@ -187,3 +195,17 @@ consistent.
 The "ust" backend uses the LTTng Userspace Tracer library.  There are no
 monitor commands built into QEMU, instead UST utilities should be used to list,
 enable/disable, and dump traces.
+
+=== SystemTap ===
+
+The "dtrace" backend uses DTrace sdt probes but has only been tested with
+SystemTap.  When SystemTap support is detected a .stp file with wrapper probes
+is generated to make use in scripts more convenient.  This step can also be
+performed manually after a build in order to change the binary name in the .stp
+probes:
+
+    scripts/tracetool --dtrace --stap \
+                      --binary path/to/qemu-binary \
+                      --target-type system \
+                      --target-arch x86_64 \
+                      <trace-events >qemu.stp
commit 59da66849215eccf1dce2154c84f217a3c39678b
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Feb 22 13:59:41 2011 +0000

    simpletrace: Make simpletrace.py a Python module
    
    The simpletrace.py script pretty-prints a binary trace file.  Most of
    the code can be reused by trace file analysis scripts, so turn it into a
    module.
    
    Here is an example script that uses the new simpletrace module:
    
      #!/usr/bin/env python
      # Print virtqueue elements that were never returned to the guest.
    
      import simpletrace
    
      class VirtqueueRequestTracker(simpletrace.Analyzer):
          def __init__(self):
              self.elems = set()
    
          def virtqueue_pop(self, vq, elem, in_num, out_num):
              self.elems.add(elem)
    
          def virtqueue_fill(self, vq, elem, length, idx):
              self.elems.remove(elem)
    
          def end(self):
              for elem in self.elems:
                  print hex(elem)
    
      simpletrace.run(VirtqueueRequestTracker())
    
    The simpletrace API is based around the Analyzer class.  Users implement
    an analyzer subclass and add methods for trace events they want to
    process.  A catchall() method is invoked for trace events which do not
    have dedicated methods.  Finally, there are also begin() and end()
    methods like in sed that can be used to perform setup or print
    statistics at the end.
    
    A binary trace file is processed either with:
    
      simpletrace.run(analyzer) # uses command-line args
    
    or with:
    
      simpletrace.process('path/to/trace-events',
                          'path/to/trace-file',
                          analyzer)
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index 553a727..9fe3dda 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -9,9 +9,9 @@
 #
 # For help see docs/tracing.txt
 
-import sys
 import struct
 import re
+import inspect
 
 header_event_id = 0xffffffffffffffff
 header_magic    = 0xf2b177cb0aa429b4
@@ -21,12 +21,8 @@ trace_fmt = '=QQQQQQQQ'
 trace_len = struct.calcsize(trace_fmt)
 event_re  = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*')
 
-def err(msg):
-    sys.stderr.write(msg + '\n')
-    sys.exit(1)
-
 def parse_events(fobj):
-    """Parse a trace-events file."""
+    """Parse a trace-events file into {event_num: (name, arg1, ...)}."""
 
     def get_argnames(args):
         """Extract argument names from a parameter list."""
@@ -45,20 +41,20 @@ def parse_events(fobj):
     return events
 
 def read_record(fobj):
-    """Deserialize a trace record from a file."""
+    """Deserialize a trace record from a file into a tuple (event_num, timestamp, arg1, ..., arg6)."""
     s = fobj.read(trace_len)
     if len(s) != trace_len:
         return None
     return struct.unpack(trace_fmt, s)
 
 def read_trace_file(fobj):
-    """Deserialize trace records from a file."""
+    """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, arg1, ..., arg6)."""
     header = read_record(fobj)
     if header is None or \
        header[0] != header_event_id or \
        header[1] != header_magic or \
        header[2] != header_version:
-        err('not a trace file or incompatible version')
+        raise ValueError('not a trace file or incompatible version')
 
     while True:
         rec = read_record(fobj)
@@ -67,27 +63,88 @@ def read_trace_file(fobj):
 
         yield rec
 
-class Formatter(object):
-    def __init__(self, events):
-        self.events = events
-        self.last_timestamp = None
-
-    def format_record(self, rec):
-        if self.last_timestamp is None:
-            self.last_timestamp = rec[1]
-        delta_ns = rec[1] - self.last_timestamp
-        self.last_timestamp = rec[1]
-
-        event = self.events[rec[0]]
-        fields = [event[0], '%0.3f' % (delta_ns / 1000.0)]
-        for i in xrange(1, len(event)):
-            fields.append('%s=0x%x' % (event[i], rec[i + 1]))
-        return ' '.join(fields)
-
-if len(sys.argv) != 3:
-    err('usage: %s <trace-events> <trace-file>' % sys.argv[0])
-
-events = parse_events(open(sys.argv[1], 'r'))
-formatter = Formatter(events)
-for rec in read_trace_file(open(sys.argv[2], 'rb')):
-    print formatter.format_record(rec)
+class Analyzer(object):
+    """A trace file analyzer which processes trace records.
+
+    An analyzer can be passed to run() or process().  The begin() method is
+    invoked, then each trace record is processed, and finally the end() method
+    is invoked.
+
+    If a method matching a trace event name exists, it is invoked to process
+    that trace record.  Otherwise the catchall() method is invoked."""
+
+    def begin(self):
+        """Called at the start of the trace."""
+        pass
+
+    def catchall(self, event, rec):
+        """Called if no specific method for processing a trace event has been found."""
+        pass
+
+    def end(self):
+        """Called at the end of the trace."""
+        pass
+
+def process(events, log, analyzer):
+    """Invoke an analyzer on each event in a log."""
+    if isinstance(events, str):
+        events = parse_events(open(events, 'r'))
+    if isinstance(log, str):
+        log = open(log, 'rb')
+
+    def build_fn(analyzer, event):
+        fn = getattr(analyzer, event[0], None)
+        if fn is None:
+            return analyzer.catchall
+
+        event_argcount = len(event) - 1
+        fn_argcount = len(inspect.getargspec(fn)[0]) - 1
+        if fn_argcount == event_argcount + 1:
+            # Include timestamp as first argument
+            return lambda _, rec: fn(*rec[1:2 + fn_argcount])
+        else:
+            # Just arguments, no timestamp
+            return lambda _, rec: fn(*rec[2:2 + fn_argcount])
+
+    analyzer.begin()
+    fn_cache = {}
+    for rec in read_trace_file(log):
+        event_num = rec[0]
+        event = events[event_num]
+        if event_num not in fn_cache:
+            fn_cache[event_num] = build_fn(analyzer, event)
+        fn_cache[event_num](event, rec)
+    analyzer.end()
+
+def run(analyzer):
+    """Execute an analyzer on a trace file given on the command-line.
+
+    This function is useful as a driver for simple analysis scripts.  More
+    advanced scripts will want to call process() instead."""
+    import sys
+
+    if len(sys.argv) != 3:
+        sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0])
+        sys.exit(1)
+
+    events = parse_events(open(sys.argv[1], 'r'))
+    process(events, sys.argv[2], analyzer)
+
+if __name__ == '__main__':
+    class Formatter(Analyzer):
+        def __init__(self):
+            self.last_timestamp = None
+
+        def catchall(self, event, rec):
+            timestamp = rec[1]
+            if self.last_timestamp is None:
+                self.last_timestamp = timestamp
+            delta_ns = timestamp - self.last_timestamp
+            self.last_timestamp = timestamp
+
+            fields = [event[0], '%0.3f' % (delta_ns / 1000.0)]
+            for i in xrange(1, len(event)):
+                fields.append('%s=0x%x' % (event[i], rec[i + 1]))
+            print ' '.join(fields)
+
+    run(Formatter())
commit 0c1592d93585ddce572a71a77534ca765c5f5d34
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 22 13:02:26 2011 +0000

    linux-user: Fix large seeks by 32 bit guest on 64 bit host
    
    When emulating a 32 bit Linux user-mode program on a 64 bit target
    we implement the llseek syscall in terms of lseek. Correct a bug
    which meant we were silently casting the result of host lseek()
    to a 32 bit integer as it passed through get_errno() and thus
    throwing away the top half.
    
    We also don't try to store the result back to userspace unless
    the seek succeeded; this matches the kernel behaviour.
    
    Thanks to Eoghan Sherry for identifying the problem and suggesting
    a solution.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cf8a4c3..23d7a63 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6127,16 +6127,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR__llseek /* Not on alpha */
     case TARGET_NR__llseek:
         {
+            int64_t res;
 #if !defined(__NR_llseek)
-            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
-            if (put_user_s64(ret, arg4))
-                goto efault;
+            res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
+            if (res == -1) {
+                ret = get_errno(res);
+            } else {
+                ret = 0;
+            }
 #else
-            int64_t res;
             ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
-            if (put_user_s64(res, arg4))
-                goto efault;
 #endif
+            if ((ret == 0) && put_user_s64(res, arg4)) {
+                goto efault;
+            }
         }
         break;
 #endif
commit 26883c699eee60c6f2dd63818a9dd470f2c567fc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 20:57:53 2011 +0000

    hw/realview: Wire up the MMC card status
    
    Instantiate the three PL061 GPIO modules the realview boards have.
    Connect the MMC card status outputs of the PL181 MMC controller
    to both the system registers and the GPIO module which handles
    internal devices.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/realview.c b/hw/realview.c
index 6eb6c6a..466b210 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -138,10 +138,11 @@ static void realview_init(ram_addr_t ram_size,
 {
     CPUState *env = NULL;
     ram_addr_t ram_offset;
-    DeviceState *dev;
+    DeviceState *dev, *sysctl, *gpio2;
     SysBusDevice *busdev;
     qemu_irq *irqp;
     qemu_irq pic[64];
+    qemu_irq mmc_irq[2];
     PCIBus *pci_bus;
     NICInfo *nd;
     i2c_bus *i2c;
@@ -218,7 +219,11 @@ static void realview_init(ram_addr_t ram_size,
     }
 
     sys_id = is_pb ? 0x01780500 : 0xc1400400;
-    arm_sysctl_init(0x10000000, sys_id, proc_id);
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_init_nofail(sysctl);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
     if (is_mpcore) {
         dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
@@ -257,9 +262,27 @@ static void realview_init(ram_addr_t ram_size,
     sysbus_create_simple("sp804", 0x10011000, pic[4]);
     sysbus_create_simple("sp804", 0x10012000, pic[5]);
 
+    sysbus_create_simple("pl061", 0x10013000, pic[6]);
+    sysbus_create_simple("pl061", 0x10014000, pic[7]);
+    gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]);
+
     sysbus_create_simple("pl110_versatile", 0x10020000, pic[23]);
 
-    sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
+    dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
+    /* Wire up MMC card detect and read-only signals. These have
+     * to go to both the PL061 GPIO and the sysctl register.
+     * Note that the PL181 orders these lines (readonly,inserted)
+     * and the PL061 has them the other way about. Also the card
+     * detect line is inverted.
+     */
+    mmc_irq[0] = qemu_irq_split(
+        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
+        qdev_get_gpio_in(gpio2, 1));
+    mmc_irq[1] = qemu_irq_split(
+        qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
+        qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
+    qdev_connect_gpio_out(dev, 0, mmc_irq[0]);
+    qdev_connect_gpio_out(dev, 1, mmc_irq[1]);
 
     sysbus_create_simple("pl031", 0x10017000, pic[10]);
 
commit 9793212bb02b9fdc2de188a42b93b17ca2689c9a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 20:57:52 2011 +0000

    hw/irq: Add qemu_irq_split() so one GPIO output can feed two inputs
    
    Add a qemu_irq_split() function which allows a board to wire a single
    GPIO output up to two GPIO inputs. This is needed for realview boards,
    where the MMC card status is visible both in a system register and
    via a PL061 GPIO module.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/irq.c b/hw/irq.c
index 7703f62..4035a8c 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -75,3 +75,18 @@ qemu_irq qemu_irq_invert(qemu_irq irq)
     qemu_irq_raise(irq);
     return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
 }
+
+static void qemu_splitirq(void *opaque, int line, int level)
+{
+    struct IRQState **irq = opaque;
+    irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
+    irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
+}
+
+qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
+{
+    qemu_irq *s = qemu_mallocz(2 * sizeof(qemu_irq));
+    s[0] = irq1;
+    s[1] = irq2;
+    return qemu_allocate_irqs(qemu_splitirq, s, 1)[0];
+}
diff --git a/hw/irq.h b/hw/irq.h
index f7849ed..389ed7a 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -30,4 +30,7 @@ void qemu_free_irqs(qemu_irq *s);
 /* Returns a new IRQ with opposite polarity.  */
 qemu_irq qemu_irq_invert(qemu_irq irq);
 
+/* Returns a new IRQ which feeds into both the passed IRQs */
+qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
+
 #endif
commit 7063f49f59807ac6f32c69281cf956d14d6c0310
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 20:57:51 2011 +0000

    hw/pl061.c: Implement ARM PL061 as well as Luminary one
    
    ARM's PL061 has a different set of ID registers to the one in the
    Luminary Stellaris; implement this so that the Linux driver can
    identify the Realview PBX PL061 correctly.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pl061.c b/hw/pl061.c
index 1997b7c..2e181f8 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -24,6 +24,8 @@ do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__);} while (0)
 #endif
 
 static const uint8_t pl061_id[12] =
+  { 0x00, 0x00, 0x00, 0x00, 0x61, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+static const uint8_t pl061_id_luminary[12] =
   { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
 
 typedef struct {
@@ -50,6 +52,7 @@ typedef struct {
     uint8_t float_high;
     qemu_irq irq;
     qemu_irq out[8];
+    const unsigned char *id;
 } pl061_state;
 
 static void pl061_update(pl061_state *s)
@@ -83,7 +86,7 @@ static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
     pl061_state *s = (pl061_state *)opaque;
 
     if (offset >= 0xfd0 && offset < 0x1000) {
-        return pl061_id[(offset - 0xfd0) >> 2];
+        return s->id[(offset - 0xfd0) >> 2];
     }
     if (offset < 0x400) {
         return s->data & (offset >> 2);
@@ -291,11 +294,11 @@ static int pl061_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static int pl061_init(SysBusDevice *dev)
+static int pl061_init(SysBusDevice *dev, const unsigned char *id)
 {
     int iomemtype;
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
-
+    s->id = id;
     iomemtype = cpu_register_io_memory(pl061_readfn,
                                        pl061_writefn, s,
                                        DEVICE_NATIVE_ENDIAN);
@@ -308,10 +311,22 @@ static int pl061_init(SysBusDevice *dev)
     return 0;
 }
 
+static int pl061_init_luminary(SysBusDevice *dev)
+{
+    return pl061_init(dev, pl061_id_luminary);
+}
+
+static int pl061_init_arm(SysBusDevice *dev)
+{
+    return pl061_init(dev, pl061_id);
+}
+
 static void pl061_register_devices(void)
 {
     sysbus_register_dev("pl061", sizeof(pl061_state),
-                        pl061_init);
+                        pl061_init_arm);
+    sysbus_register_dev("pl061_luminary", sizeof(pl061_state),
+                        pl061_init_luminary);
 }
 
 device_init(pl061_register_devices)
diff --git a/hw/stellaris.c b/hw/stellaris.c
index b903273..5d8bd55 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1338,7 +1338,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
 
     for (i = 0; i < 7; i++) {
         if (board->dc4 & (1 << i)) {
-            gpio_dev[i] = sysbus_create_simple("pl061", gpio_addr[i],
+            gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
                                                pic[gpio_irq[i]]);
             for (j = 0; j < 8; j++) {
                 gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j);
commit b50ff6f524fae78c7d79b27b00af701d7c28e80c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 20:57:50 2011 +0000

    hw/arm_sysctl.c: Wire MCI register MMC card status bits to GPIO inputs
    
    Implement some GPIO inputs which a board can connect up to set the
    MMC card status bits in the MCI register.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index d8b062c..799b007 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -26,6 +26,7 @@ typedef struct {
     uint32_t nvflags;
     uint32_t resetlevel;
     uint32_t proc_id;
+    uint32_t sys_mci;
 } arm_sysctl_state;
 
 static const VMStateDescription vmstate_arm_sysctl = {
@@ -44,6 +45,21 @@ static const VMStateDescription vmstate_arm_sysctl = {
     }
 };
 
+/* The PB926 actually uses a different format for
+ * its SYS_ID register. Fortunately the bits which are
+ * board type on later boards are distinct.
+ */
+#define BOARD_ID_PB926 0x100
+#define BOARD_ID_EB 0x140
+#define BOARD_ID_PBA8 0x178
+#define BOARD_ID_PBX 0x182
+
+static int board_id(arm_sysctl_state *s)
+{
+    /* Extract the board ID field from the SYS_ID register value */
+    return (s->sys_id >> 16) & 0xfff;
+}
+
 static void arm_sysctl_reset(DeviceState *d)
 {
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sysbus_from_qdev(d));
@@ -92,7 +108,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
     case 0x44: /* PCICTL */
         return 1;
     case 0x48: /* MCI */
-        return 0;
+        return s->sys_mci;
     case 0x4c: /* FLASH */
         return 0;
     case 0x50: /* CLCD */
@@ -218,6 +234,34 @@ static CPUWriteMemoryFunc * const arm_sysctl_writefn[] = {
    arm_sysctl_write
 };
 
+static void arm_sysctl_gpio_set(void *opaque, int line, int level)
+{
+    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
+    switch (line) {
+    case ARM_SYSCTL_GPIO_MMC_WPROT:
+    {
+        /* For PB926 and EB write-protect is bit 2 of SYS_MCI;
+         * for all later boards it is bit 1.
+         */
+        int bit = 2;
+        if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) {
+            bit = 4;
+        }
+        s->sys_mci &= ~bit;
+        if (level) {
+            s->sys_mci |= bit;
+        }
+        break;
+    }
+    case ARM_SYSCTL_GPIO_MMC_CARDIN:
+        s->sys_mci &= ~1;
+        if (level) {
+            s->sys_mci |= 1;
+        }
+        break;
+    }
+}
+
 static int arm_sysctl_init1(SysBusDevice *dev)
 {
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
@@ -227,6 +271,7 @@ static int arm_sysctl_init1(SysBusDevice *dev)
                                        arm_sysctl_writefn, s,
                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
+    qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
     /* ??? Save/restore.  */
     return 0;
 }
diff --git a/hw/primecell.h b/hw/primecell.h
index fb456ad..de7d6f2 100644
--- a/hw/primecell.h
+++ b/hw/primecell.h
@@ -11,4 +11,8 @@ void *pl080_init(uint32_t base, qemu_irq irq, int nchannels);
 /* arm_sysctl.c */
 void arm_sysctl_init(uint32_t base, uint32_t sys_id, uint32_t proc_id);
 
+/* arm_sysctl GPIO lines */
+#define ARM_SYSCTL_GPIO_MMC_WPROT 0
+#define ARM_SYSCTL_GPIO_MMC_CARDIN 1
+
 #endif
commit c31a4724e25ef867acda0eafc7ddb3999e4bb204
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 20:57:49 2011 +0000

    hw/pl181: Implement GPIO output pins for card status
    
    Add two GPIO output pins to the PL181 model to indicate the card
    present and readonly status information. On ARM boards these usually
    are reflected in a system register.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pl181.c b/hw/pl181.c
index 36d9d02..6bc79f5 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -47,6 +47,8 @@ typedef struct {
     int linux_hack;
     uint32_t fifo[PL181_FIFO_LEN];
     qemu_irq irq[2];
+    /* GPIO outputs for 'card is readonly' and 'card inserted' */
+    qemu_irq cardstatus[2];
 } pl181_state;
 
 #define PL181_CMD_INDEX     0x3f
@@ -444,6 +446,9 @@ static void pl181_reset(void *opaque)
     s->linux_hack = 0;
     s->mask[0] = 0;
     s->mask[1] = 0;
+
+    /* We can assume our GPIO outputs have been wired up now */
+    sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
 }
 
 static int pl181_init(SysBusDevice *dev)
@@ -457,6 +462,7 @@ static int pl181_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
+    qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
     qemu_register_reset(pl181_reset, s);
commit 444dd39b5f226926e8b8a950821e6f48a5da3ccd
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Jan 26 12:31:00 2011 +0000

    lsi53c895a: Update dnad when skipping MSGOUT bytes
    
    Update not only dbc but also dnad when skipping bytes during the MSGOUT
    phase.  Previously only dbc was updated which is probably wrong and
    could lead to bogus message codes being read.
    
    Tested on Linux and Windows Server 2003.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 9c761cd..84a4992 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -842,6 +842,13 @@ static uint8_t lsi_get_msgbyte(LSIState *s)
     return data;
 }
 
+/* Skip the next n bytes during a MSGOUT phase. */
+static void lsi_skip_msgbytes(LSIState *s, unsigned int n)
+{
+    s->dnad += n;
+    s->dbc  -= n;
+}
+
 static void lsi_do_msgout(LSIState *s)
 {
     uint8_t msg;
@@ -869,11 +876,11 @@ static void lsi_do_msgout(LSIState *s)
             switch (msg) {
             case 1:
                 DPRINTF("SDTR (ignored)\n");
-                s->dbc -= 2;
+                lsi_skip_msgbytes(s, 2);
                 break;
             case 3:
                 DPRINTF("WDTR (ignored)\n");
-                s->dbc -= 1;
+                lsi_skip_msgbytes(s, 1);
                 break;
             default:
                 goto bad;
commit dcfd08653b8ceab07aed8415aa650254a94a098c
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sun Mar 6 13:23:13 2011 +0000

    WIN32: Add missing include for 'struct timeval', used in vnc.h
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-common.h b/qemu-common.h
index 40dad52..18e648f 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -33,6 +33,7 @@ typedef struct DeviceState DeviceState;
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <assert.h>
 
 #ifndef O_LARGEFILE
commit 219982ef42154ad58a629f59267797c5454fc742
Author: Gerhard Wiesinger <lists at wiesinger.com>
Date:   Sat Mar 5 13:44:39 2011 +0100

    hw/pcnet.c: Fix EPROM contents to suit AMD netware drivers
    
    bugfix under DOS for AMD netware driver:
    AMD PCNTNW Ethernet MLID v3.10 (960115), network card not found
    
    bugfix works well under DOS with:
    1.) AMD NDIS driver v2.0.1
    2.) AMD PCNTNW Ethernet MLID v3.10 (960115)
    3.) Knoppix 6.2
    
    Signed-off-by: Gerhard Wiesinger <lists at wiesinger.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pcnet.c b/hw/pcnet.c
index db52dc5..6dfdcc4 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1562,8 +1562,24 @@ void pcnet_h_reset(void *opaque)
 
     /* Initialize the PROM */
 
+    /*
+      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
+      page 95
+    */
     memcpy(s->prom, s->conf.macaddr.a, 6);
+    /* Reserved Location: must be 00h */
+    s->prom[6] = s->prom[7] = 0x00;
+    /* Reserved Location: must be 00h */
+    s->prom[8] = 0x00;
+    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
+    s->prom[9] = 0x11;
+    /* User programmable space, init with 0 */
+    s->prom[10] = s->prom[11] = 0x00;
+    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
+       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
     s->prom[12] = s->prom[13] = 0x00;
+    /* Must be ASCII W (57h) if compatibility to AMD
+       driver software is desired */
     s->prom[14] = s->prom[15] = 0x57;
 
     for (i = 0,checksum = 0; i < 16; i++)
commit 60c07d933c66c4b30a83b7ccbc8a0cb3df1b2d0e
Author: Vincent Palatin <vpalatin at chromium.org>
Date:   Wed Mar 2 17:25:02 2011 -0500

    net: fix qemu_can_send_packet logic
    
    If any of the clients is not ready to receive (ie it has a can_receive
    callback and can_receive() returns false), we don't want to start
    sending, else this client may miss/discard the packet.
    
    I got this behaviour with the following setup :
    the emulated machine is using an USB-ethernet adapter, it is connected
    to the network using SLIRP and I'm dumping the traffic in a .pcap file.
    As per the following command line :
    -net nic,model=usb,vlan=1 -net user,vlan=1 -net dump,vlan=1,file=/tmp/pkt.pcap
    Every time that two packets are coming in a row from the host, the
    usb-net code will receive the first one, then returns 0 to can_receive
    call since it has a 1 packet long queue. But as the dump code is always
    ready to receive, qemu_can_send_packet will return true and the next
    packet will discard the previous one in the usb-net code.
    
    Signed-off-by: Vincent Palatin <vpalatin at chromium.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/net.c b/net.c
index ec4745d..72ac4cf 100644
--- a/net.c
+++ b/net.c
@@ -411,11 +411,11 @@ int qemu_can_send_packet(VLANClientState *sender)
         }
 
         /* no can_receive() handler, they can always receive */
-        if (!vc->info->can_receive || vc->info->can_receive(vc)) {
-            return 1;
+        if (vc->info->can_receive && !vc->info->can_receive(vc)) {
+            return 0;
         }
     }
-    return 0;
+    return 1;
 }
 
 static ssize_t qemu_deliver_packet(VLANClientState *sender,
commit 24ac3a7d4eacea38d514dbf50baa845e5bc6840b
Author: Vincent Palatin <vpalatin at chromium.org>
Date:   Wed Mar 2 17:25:01 2011 -0500

    net: fix trace when debug is activated in slirp
    
    make the code compile correctly when DEBUG is activated.
    
    Signed-off-by: Vincent Palatin <vpalatin at chromium.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/slirp/bootp.c b/slirp/bootp.c
index 0905c6d..1eb2ed1 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -284,7 +284,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
     } else {
         static const char nak_msg[] = "requested address not available";
 
-        DPRINTF("nak'ed addr=%08x\n", ntohl(preq_addr->s_addr));
+        DPRINTF("nak'ed addr=%08x\n", ntohl(preq_addr.s_addr));
 
         *q++ = RFC2132_MSG_TYPE;
         *q++ = 1;
commit 4e6557124c2b48725d092fded67e71f0bf78415f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 10 16:53:04 2011 +0000

    linux-user: fix compile failure if !CONFIG_USE_GUEST_BASE
    
    If CONFIG_USE_GUEST_BASE is not defined, gcc complains:
     linux-user/mmap.c:235: error: comparison of unsigned expression >= 0 is always true
    
    because RESERVED_VA is #defined to 0. Since mmap_find_vma_reserved()
    will never be called anyway if RESERVED_VA is always 0, fix this by
    simply #ifdef'ing away the function and its callsite.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index abf21f6..0cf22f8 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -216,6 +216,7 @@ static abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
 
 unsigned long last_brk;
 
+#ifdef CONFIG_USE_GUEST_BASE
 /* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk
    of guest address space.  */
 static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
@@ -249,6 +250,7 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
     mmap_next_start = addr;
     return last_addr;
 }
+#endif
 
 /*
  * Find and reserve a free memory area of size 'size'. The search
@@ -271,9 +273,11 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
 
     size = HOST_PAGE_ALIGN(size);
 
+#ifdef CONFIG_USE_GUEST_BASE
     if (RESERVED_VA) {
         return mmap_find_vma_reserved(start, size);
     }
+#endif
 
     addr = start;
     wrapped = repeat = 0;
commit b46d97f2d2fd7c099b11e610de630918dfd11fa1
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Mar 3 21:42:28 2011 +0000

    virtio-net: Fix lduw_p() pointer argument of wrong size
    
    A pointer to a size_t variable was passed as the void * pointer to
    lduw_p() in virtio_net_receive().  Instead of acting on the 16-bit value
    this caused failure on big-endian hosts.
    
    Avoid this issue in the future by using stw_p() instead.  In general we
    should use ld*_p() for loading from target memory and st*_p() for
    storing to target memory anyway, not the other way around.
    
    Also tighten up a correct use of lduw_p() when stw_p() should be used
    instead in virtio_net_get_config().
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 20cf680..5962298 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -79,7 +79,7 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
     VirtIONet *n = to_virtio_net(vdev);
     struct virtio_net_config netcfg;
 
-    netcfg.status = lduw_p(&n->status);
+    stw_p(&netcfg.status, n->status);
     memcpy(netcfg.mac, n->mac, ETH_ALEN);
     memcpy(config, &netcfg, sizeof(netcfg));
 }
@@ -679,7 +679,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
     }
 
     if (mhdr) {
-        mhdr->num_buffers = lduw_p(&i);
+        stw_p(&mhdr->num_buffers, i);
     }
 
     virtqueue_flush(n->rx_vq, i);
commit efac4154711863128558b5b65486ac79b760367e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Feb 24 12:31:41 2011 +0100

    target-sh4: move intr_at_halt out of cpu_halted()
    
    All targets except SH4 have the same cpu_halted() routine, and it has
    only one caller. It is therefore a good candidate for inlining.
    
    The difference is the handling of the intr_at_halt, which is necessary
    to ignore SR.BL when sleeping. Move intr_at_halt handling out of it, by
    setting this variable while executing the sleep instruction, and
    clearing it when the CPU has been woken-up by an interrupt, whatever the
    state of SR.BL. Also rename this variable in_sleep.
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 789d188..74ff97a 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -184,7 +184,7 @@ typedef struct CPUSH4State {
     uint32_t cvr;		/* Cache Version Register */
 
     void *intc_handle;
-    int intr_at_halt;		/* SR_BL ignored during sleep */
+    int in_sleep;		/* SR_BL ignored during sleep */
     memory_content *movcal_backup;
     memory_content **movcal_backup_tail;
 } CPUSH4State;
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index 2999c02..61bc121 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -37,7 +37,6 @@ static inline int cpu_halted(CPUState *env) {
         return 0;
     if (cpu_has_work(env)) {
         env->halted = 0;
-        env->intr_at_halt = 1;
         return 0;
     }
     return EXCP_HALTED;
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index d2038bd..8f36d31 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -90,11 +90,11 @@ void do_interrupt(CPUState * env)
         if (do_exp && env->exception_index != 0x1e0) {
             env->exception_index = 0x000; /* masked exception -> reset */
         }
-        if (do_irq && !env->intr_at_halt) {
+        if (do_irq && !env->in_sleep) {
             return; /* masked */
         }
-        env->intr_at_halt = 0;
     }
+    env->in_sleep = 0;
 
     if (do_irq) {
         irq_vector = sh_intc_get_pending_vector(env->intc_handle,
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 30f9842..b8f4ca2 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -119,6 +119,7 @@ void helper_debug(void)
 void helper_sleep(uint32_t next_pc)
 {
     env->halted = 1;
+    env->in_sleep = 1;
     env->exception_index = EXCP_HLT;
     env->pc = next_pc;
     cpu_loop_exit();
commit 8a231487bc45ad5e5a70c747d9f35027922fb640
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Mar 3 15:13:42 2011 +0100

    pxa2xx: port pxa2xx_rtc to using qdev/vmstate
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index d7c32ee..d982f00 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -146,34 +146,6 @@ typedef struct {
 
     /* Performance monitoring */
     uint32_t pmnc;
-
-    /* Real-Time clock */
-    target_phys_addr_t rtc_base;
-    uint32_t rttr;
-    uint32_t rtsr;
-    uint32_t rtar;
-    uint32_t rdar1;
-    uint32_t rdar2;
-    uint32_t ryar1;
-    uint32_t ryar2;
-    uint32_t swar1;
-    uint32_t swar2;
-    uint32_t piar;
-    uint32_t last_rcnr;
-    uint32_t last_rdcr;
-    uint32_t last_rycr;
-    uint32_t last_swcr;
-    uint32_t last_rtcpicr;
-    int64_t last_hz;
-    int64_t last_sw;
-    int64_t last_pi;
-    QEMUTimer *rtc_hz;
-    QEMUTimer *rtc_rdal1;
-    QEMUTimer *rtc_rdal2;
-    QEMUTimer *rtc_swal1;
-    QEMUTimer *rtc_swal2;
-    QEMUTimer *rtc_pi;
-    qemu_irq rtc_irq;
 } PXA2xxState;
 
 struct PXA2xxI2SState {
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index dfea01a..4c7b9e6 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -13,7 +13,6 @@
 #include "pc.h"
 #include "i2c.h"
 #include "ssi.h"
-#include "qemu-timer.h"
 #include "qemu-char.h"
 #include "blockdev.h"
 
@@ -886,12 +885,41 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
 #define RTCPICR		0x34	/* RTC Periodic Interrupt Counter register */
 #define PIAR		0x38	/* RTC Periodic Interrupt Alarm register */
 
-static inline void pxa2xx_rtc_int_update(PXA2xxState *s)
+typedef struct {
+    SysBusDevice busdev;
+    uint32_t rttr;
+    uint32_t rtsr;
+    uint32_t rtar;
+    uint32_t rdar1;
+    uint32_t rdar2;
+    uint32_t ryar1;
+    uint32_t ryar2;
+    uint32_t swar1;
+    uint32_t swar2;
+    uint32_t piar;
+    uint32_t last_rcnr;
+    uint32_t last_rdcr;
+    uint32_t last_rycr;
+    uint32_t last_swcr;
+    uint32_t last_rtcpicr;
+    int64_t last_hz;
+    int64_t last_sw;
+    int64_t last_pi;
+    QEMUTimer *rtc_hz;
+    QEMUTimer *rtc_rdal1;
+    QEMUTimer *rtc_rdal2;
+    QEMUTimer *rtc_swal1;
+    QEMUTimer *rtc_swal2;
+    QEMUTimer *rtc_pi;
+    qemu_irq rtc_irq;
+} PXA2xxRTCState;
+
+static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s)
 {
     qemu_set_irq(s->rtc_irq, !!(s->rtsr & 0x2553));
 }
 
-static void pxa2xx_rtc_hzupdate(PXA2xxState *s)
+static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
 {
     int64_t rt = qemu_get_clock(rt_clock);
     s->last_rcnr += ((rt - s->last_hz) << 15) /
@@ -901,7 +929,7 @@ static void pxa2xx_rtc_hzupdate(PXA2xxState *s)
     s->last_hz = rt;
 }
 
-static void pxa2xx_rtc_swupdate(PXA2xxState *s)
+static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
 {
     int64_t rt = qemu_get_clock(rt_clock);
     if (s->rtsr & (1 << 12))
@@ -909,7 +937,7 @@ static void pxa2xx_rtc_swupdate(PXA2xxState *s)
     s->last_sw = rt;
 }
 
-static void pxa2xx_rtc_piupdate(PXA2xxState *s)
+static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
 {
     int64_t rt = qemu_get_clock(rt_clock);
     if (s->rtsr & (1 << 15))
@@ -917,7 +945,7 @@ static void pxa2xx_rtc_piupdate(PXA2xxState *s)
     s->last_pi = rt;
 }
 
-static inline void pxa2xx_rtc_alarm_update(PXA2xxState *s,
+static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s,
                 uint32_t rtsr)
 {
     if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
@@ -962,7 +990,7 @@ static inline void pxa2xx_rtc_alarm_update(PXA2xxState *s,
 
 static inline void pxa2xx_rtc_hz_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 0);
     pxa2xx_rtc_alarm_update(s, s->rtsr);
     pxa2xx_rtc_int_update(s);
@@ -970,7 +998,7 @@ static inline void pxa2xx_rtc_hz_tick(void *opaque)
 
 static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 4);
     pxa2xx_rtc_alarm_update(s, s->rtsr);
     pxa2xx_rtc_int_update(s);
@@ -978,7 +1006,7 @@ static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
 
 static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 6);
     pxa2xx_rtc_alarm_update(s, s->rtsr);
     pxa2xx_rtc_int_update(s);
@@ -986,7 +1014,7 @@ static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
 
 static inline void pxa2xx_rtc_swal1_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 8);
     pxa2xx_rtc_alarm_update(s, s->rtsr);
     pxa2xx_rtc_int_update(s);
@@ -994,7 +1022,7 @@ static inline void pxa2xx_rtc_swal1_tick(void *opaque)
 
 static inline void pxa2xx_rtc_swal2_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 10);
     pxa2xx_rtc_alarm_update(s, s->rtsr);
     pxa2xx_rtc_int_update(s);
@@ -1002,7 +1030,7 @@ static inline void pxa2xx_rtc_swal2_tick(void *opaque)
 
 static inline void pxa2xx_rtc_pi_tick(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
     s->rtsr |= (1 << 13);
     pxa2xx_rtc_piupdate(s);
     s->last_rtcpicr = 0;
@@ -1012,7 +1040,7 @@ static inline void pxa2xx_rtc_pi_tick(void *opaque)
 
 static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
 
     switch (addr) {
     case RTTR:
@@ -1058,7 +1086,7 @@ static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
 static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
 
     switch (addr) {
     case RTTR:
@@ -1170,10 +1198,12 @@ static CPUWriteMemoryFunc * const pxa2xx_rtc_writefn[] = {
     pxa2xx_rtc_write,
 };
 
-static void pxa2xx_rtc_init(PXA2xxState *s)
+static int pxa2xx_rtc_init(SysBusDevice *dev)
 {
+    PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
     struct tm tm;
     int wom;
+    int iomemtype;
 
     s->rttr = 0x7fff;
     s->rtsr = 0;
@@ -1198,65 +1228,71 @@ static void pxa2xx_rtc_init(PXA2xxState *s)
     s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s);
     s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
 
-    s->rtc_irq = qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM);
+    sysbus_init_irq(dev, &s->rtc_irq);
+
+    iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
+                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
+    sysbus_init_mmio(dev, 0x10000, iomemtype);
+
+    return 0;
 }
 
-static void pxa2xx_rtc_save(QEMUFile *f, void *opaque)
+static void pxa2xx_rtc_pre_save(void *opaque)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
 
     pxa2xx_rtc_hzupdate(s);
     pxa2xx_rtc_piupdate(s);
     pxa2xx_rtc_swupdate(s);
+}
 
-    qemu_put_be32s(f, &s->rttr);
-    qemu_put_be32s(f, &s->rtsr);
-    qemu_put_be32s(f, &s->rtar);
-    qemu_put_be32s(f, &s->rdar1);
-    qemu_put_be32s(f, &s->rdar2);
-    qemu_put_be32s(f, &s->ryar1);
-    qemu_put_be32s(f, &s->ryar2);
-    qemu_put_be32s(f, &s->swar1);
-    qemu_put_be32s(f, &s->swar2);
-    qemu_put_be32s(f, &s->piar);
-    qemu_put_be32s(f, &s->last_rcnr);
-    qemu_put_be32s(f, &s->last_rdcr);
-    qemu_put_be32s(f, &s->last_rycr);
-    qemu_put_be32s(f, &s->last_swcr);
-    qemu_put_be32s(f, &s->last_rtcpicr);
-    qemu_put_sbe64s(f, &s->last_hz);
-    qemu_put_sbe64s(f, &s->last_sw);
-    qemu_put_sbe64s(f, &s->last_pi);
-}
-
-static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id)
+static int pxa2xx_rtc_post_load(void *opaque, int version_id)
 {
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    qemu_get_be32s(f, &s->rttr);
-    qemu_get_be32s(f, &s->rtsr);
-    qemu_get_be32s(f, &s->rtar);
-    qemu_get_be32s(f, &s->rdar1);
-    qemu_get_be32s(f, &s->rdar2);
-    qemu_get_be32s(f, &s->ryar1);
-    qemu_get_be32s(f, &s->ryar2);
-    qemu_get_be32s(f, &s->swar1);
-    qemu_get_be32s(f, &s->swar2);
-    qemu_get_be32s(f, &s->piar);
-    qemu_get_be32s(f, &s->last_rcnr);
-    qemu_get_be32s(f, &s->last_rdcr);
-    qemu_get_be32s(f, &s->last_rycr);
-    qemu_get_be32s(f, &s->last_swcr);
-    qemu_get_be32s(f, &s->last_rtcpicr);
-    qemu_get_sbe64s(f, &s->last_hz);
-    qemu_get_sbe64s(f, &s->last_sw);
-    qemu_get_sbe64s(f, &s->last_pi);
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
 
     pxa2xx_rtc_alarm_update(s, s->rtsr);
 
     return 0;
 }
 
+static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
+    .name = "pxa2xx_rtc",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save = pxa2xx_rtc_pre_save,
+    .post_load = pxa2xx_rtc_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(rttr, PXA2xxRTCState),
+        VMSTATE_UINT32(rtsr, PXA2xxRTCState),
+        VMSTATE_UINT32(rtar, PXA2xxRTCState),
+        VMSTATE_UINT32(rdar1, PXA2xxRTCState),
+        VMSTATE_UINT32(rdar2, PXA2xxRTCState),
+        VMSTATE_UINT32(ryar1, PXA2xxRTCState),
+        VMSTATE_UINT32(ryar2, PXA2xxRTCState),
+        VMSTATE_UINT32(swar1, PXA2xxRTCState),
+        VMSTATE_UINT32(swar2, PXA2xxRTCState),
+        VMSTATE_UINT32(piar, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rcnr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rdcr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rycr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_swcr, PXA2xxRTCState),
+        VMSTATE_UINT32(last_rtcpicr, PXA2xxRTCState),
+        VMSTATE_INT64(last_hz, PXA2xxRTCState),
+        VMSTATE_INT64(last_sw, PXA2xxRTCState),
+        VMSTATE_INT64(last_pi, PXA2xxRTCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo pxa2xx_rtc_sysbus_info = {
+    .init       = pxa2xx_rtc_init,
+    .qdev.name  = "pxa2xx_rtc",
+    .qdev.desc  = "PXA2xx RTC Controller",
+    .qdev.size  = sizeof(PXA2xxRTCState),
+    .qdev.vmsd  = &vmstate_pxa2xx_rtc_regs,
+};
+
 /* I2C Interface */
 typedef struct {
     i2c_slave i2c;
@@ -2188,13 +2224,8 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
     s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
 
-    s->rtc_base = 0x40900000;
-    iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
-    pxa2xx_rtc_init(s);
-    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
-                    pxa2xx_rtc_load, s);
+    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
@@ -2329,13 +2360,8 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
     s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
 
-    s->rtc_base = 0x40900000;
-    iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
-    pxa2xx_rtc_init(s);
-    register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
-                    pxa2xx_rtc_load, s);
+    sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
 
     s->i2c[0] = pxa2xx_i2c_init(0x40301600,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
@@ -2358,6 +2384,7 @@ static void pxa2xx_register_devices(void)
     i2c_register_slave(&pxa2xx_i2c_slave_info);
     sysbus_register_dev("pxa2xx-ssp", sizeof(PXA2xxSSPState), pxa2xx_ssp_init);
     sysbus_register_withprop(&pxa2xx_i2c_info);
+    sysbus_register_withprop(&pxa2xx_rtc_sysbus_info);
 }
 
 device_init(pxa2xx_register_devices)
commit f114c826122759c619ef3ca55b6cfbe7d4d35bc3
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Mar 3 15:06:03 2011 +0100

    pxa2xx_dma: Get rid of a forward declaration.

diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 6c599a0..a67498b 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -426,7 +426,30 @@ static CPUWriteMemoryFunc * const pxa2xx_dma_writefn[] = {
     pxa2xx_dma_write
 };
 
-static void pxa2xx_dma_request(void *opaque, int req_num, int on);
+static void pxa2xx_dma_request(void *opaque, int req_num, int on)
+{
+    PXA2xxDMAState *s = opaque;
+    int ch;
+    if (req_num < 0 || req_num >= PXA2XX_DMA_NUM_REQUESTS)
+        hw_error("%s: Bad DMA request %i\n", __FUNCTION__, req_num);
+
+    if (!(s->req[req_num] & DRCMR_MAPVLD))
+        return;
+    ch = s->req[req_num] & DRCMR_CHLNUM;
+
+    if (!s->chan[ch].request && on)
+        s->chan[ch].state |= DCSR_RASINTR;
+    else
+        s->chan[ch].state &= ~DCSR_RASINTR;
+    if (s->chan[ch].request && !on)
+        s->chan[ch].state |= DCSR_EORINT;
+
+    s->chan[ch].request = on;
+    if (on) {
+        pxa2xx_dma_run(s);
+        pxa2xx_dma_update(s, ch);
+    }
+}
 
 static int pxa2xx_dma_init(SysBusDevice *dev)
 {
@@ -484,31 +507,6 @@ DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq)
     return dev;
 }
 
-static void pxa2xx_dma_request(void *opaque, int req_num, int on)
-{
-    PXA2xxDMAState *s = opaque;
-    int ch;
-    if (req_num < 0 || req_num >= PXA2XX_DMA_NUM_REQUESTS)
-        hw_error("%s: Bad DMA request %i\n", __FUNCTION__, req_num);
-
-    if (!(s->req[req_num] & DRCMR_MAPVLD))
-        return;
-    ch = s->req[req_num] & DRCMR_CHLNUM;
-
-    if (!s->chan[ch].request && on)
-        s->chan[ch].state |= DCSR_RASINTR;
-    else
-        s->chan[ch].state &= ~DCSR_RASINTR;
-    if (s->chan[ch].request && !on)
-        s->chan[ch].state |= DCSR_EORINT;
-
-    s->chan[ch].request = on;
-    if (on) {
-        pxa2xx_dma_run(s);
-        pxa2xx_dma_update(s, ch);
-    }
-}
-
 static bool is_version_0(void *opaque, int version_id)
 {
     return version_id == 0;
commit 2115c01924ff355c48c10ef08fe5a87c958eb54a
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Mar 3 15:04:51 2011 +0100

    pxa2xx_dma: port to qdev/vmstate
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 7d7f49e..d7c32ee 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -71,12 +71,8 @@ DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
 void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
 
 /* pxa2xx_dma.c */
-typedef struct PXA2xxDMAState PXA2xxDMAState;
-PXA2xxDMAState *pxa255_dma_init(target_phys_addr_t base,
-                qemu_irq irq);
-PXA2xxDMAState *pxa27x_dma_init(target_phys_addr_t base,
-                qemu_irq irq);
-void pxa2xx_dma_request(PXA2xxDMAState *s, int req_num, int on);
+DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq);
+DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq);
 
 /* pxa2xx_lcd.c */
 typedef struct PXA2xxLCDState PXA2xxLCDState;
@@ -88,7 +84,8 @@ void pxa2xx_lcdc_oritentation(void *opaque, int angle);
 /* pxa2xx_mmci.c */
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
 PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
-                BlockDriverState *bd, qemu_irq irq, void *dma);
+                BlockDriverState *bd, qemu_irq irq,
+                qemu_irq rx_dma, qemu_irq tx_dma);
 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
                 qemu_irq coverswitch);
 
@@ -123,7 +120,7 @@ typedef struct {
     CPUState *env;
     DeviceState *pic;
     qemu_irq reset;
-    PXA2xxDMAState *dma;
+    DeviceState *dma;
     DeviceState *gpio;
     PXA2xxLCDState *lcd;
     SSIBus **ssp;
@@ -181,7 +178,8 @@ typedef struct {
 
 struct PXA2xxI2SState {
     qemu_irq irq;
-    PXA2xxDMAState *dma;
+    qemu_irq rx_dma;
+    qemu_irq tx_dma;
     void (*data_req)(void *, int, int);
 
     uint32_t control[2];
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 7c31fab..dfea01a 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1585,8 +1585,8 @@ static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
     tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
             i2s->enable && !SACR_DPRL(i2s->control[1]);
 
-    pxa2xx_dma_request(i2s->dma, PXA2XX_RX_RQ_I2S, rfs);
-    pxa2xx_dma_request(i2s->dma, PXA2XX_TX_RQ_I2S, tfs);
+    qemu_set_irq(i2s->rx_dma, rfs);
+    qemu_set_irq(i2s->tx_dma, tfs);
 
     i2s->status &= 0xe0;
     if (i2s->fifo_len < 16 || !i2s->enable)
@@ -1769,14 +1769,15 @@ static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
 }
 
 static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
-                qemu_irq irq, PXA2xxDMAState *dma)
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
 {
     int iomemtype;
     PXA2xxI2SState *s = (PXA2xxI2SState *)
             qemu_mallocz(sizeof(PXA2xxI2SState));
 
     s->irq = irq;
-    s->dma = dma;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
     s->data_req = pxa2xx_i2s_data_req;
 
     pxa2xx_i2s_reset(s);
@@ -1794,7 +1795,8 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
 /* PXA Fast Infra-red Communications Port */
 struct PXA2xxFIrState {
     qemu_irq irq;
-    PXA2xxDMAState *dma;
+    qemu_irq rx_dma;
+    qemu_irq tx_dma;
     int enable;
     CharDriverState *chr;
 
@@ -1848,8 +1850,8 @@ static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
             (s->status[0] & (1 << 1));			/* TUR */
     intr |= s->status[0] & 0x25;			/* FRE, RAB, EIF */
 
-    pxa2xx_dma_request(s->dma, PXA2XX_RX_RQ_ICP, (s->status[0] >> 4) & 1);
-    pxa2xx_dma_request(s->dma, PXA2XX_TX_RQ_ICP, (s->status[0] >> 3) & 1);
+    qemu_set_irq(s->rx_dma, (s->status[0] >> 4) & 1);
+    qemu_set_irq(s->tx_dma, (s->status[0] >> 3) & 1);
 
     qemu_set_irq(s->irq, intr && s->enable);
 }
@@ -2028,7 +2030,7 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
-                qemu_irq irq, PXA2xxDMAState *dma,
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
                 CharDriverState *chr)
 {
     int iomemtype;
@@ -2036,7 +2038,8 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
             qemu_mallocz(sizeof(PXA2xxFIrState));
 
     s->irq = irq;
-    s->dma = dma;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
     s->chr = chr;
 
     pxa2xx_fir_reset(s);
@@ -2116,7 +2119,9 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
 
     for (i = 0; pxa270_serial[i].io_base; i ++)
         if (serial_hds[i])
@@ -2134,7 +2139,9 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     if (serial_hds[i])
         s->fir = pxa2xx_fir_init(0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        s->dma, serial_hds[i]);
+                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
+                        serial_hds[i]);
 
     s->lcd = pxa2xx_lcdc_init(0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
@@ -2195,7 +2202,9 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
     s->i2s = pxa2xx_i2s_init(0x40400000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S), s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
 
     s->kp = pxa27x_keypad_init(0x41500000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
@@ -2250,7 +2259,9 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
 
     for (i = 0; pxa255_serial[i].io_base; i ++)
         if (serial_hds[i]) {
@@ -2269,7 +2280,9 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     if (serial_hds[i])
         s->fir = pxa2xx_fir_init(0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        s->dma, serial_hds[i]);
+                        qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
+                        qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
+                        serial_hds[i]);
 
     s->lcd = pxa2xx_lcdc_init(0x44000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
@@ -2330,7 +2343,9 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
     s->i2s = pxa2xx_i2s_init(0x40400000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S), s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
+                    qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
 
     /* GPIO1 resets the processor */
     /* The handler can be overridden by board-specific code */
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 92c3e1e..6c599a0 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -10,6 +10,12 @@
 
 #include "hw.h"
 #include "pxa.h"
+#include "sysbus.h"
+
+#define PXA255_DMA_NUM_CHANNELS 16
+#define PXA27X_DMA_NUM_CHANNELS 32
+
+#define PXA2XX_DMA_NUM_REQUESTS 75
 
 typedef struct {
     target_phys_addr_t descr;
@@ -20,7 +26,8 @@ typedef struct {
     int request;
 } PXA2xxDMAChannel;
 
-struct PXA2xxDMAState {
+typedef struct PXA2xxDMAState {
+    SysBusDevice busdev;
     qemu_irq irq;
 
     uint32_t stopintr;
@@ -35,16 +42,11 @@ struct PXA2xxDMAState {
     int channels;
     PXA2xxDMAChannel *chan;
 
-    uint8_t *req;
+    uint8_t req[PXA2XX_DMA_NUM_REQUESTS];
 
     /* Flag to avoid recursive DMA invocations.  */
     int running;
-};
-
-#define PXA255_DMA_NUM_CHANNELS	16
-#define PXA27X_DMA_NUM_CHANNELS	32
-
-#define PXA2XX_DMA_NUM_REQUESTS	75
+} PXA2xxDMAState;
 
 #define DCSR0	0x0000	/* DMA Control / Status register for Channel 0 */
 #define DCSR31	0x007c	/* DMA Control / Status register for Channel 31 */
@@ -424,73 +426,19 @@ static CPUWriteMemoryFunc * const pxa2xx_dma_writefn[] = {
     pxa2xx_dma_write
 };
 
-static void pxa2xx_dma_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->channels);
-
-    qemu_put_be32s(f, &s->stopintr);
-    qemu_put_be32s(f, &s->eorintr);
-    qemu_put_be32s(f, &s->rasintr);
-    qemu_put_be32s(f, &s->startintr);
-    qemu_put_be32s(f, &s->endintr);
-    qemu_put_be32s(f, &s->align);
-    qemu_put_be32s(f, &s->pio);
-
-    qemu_put_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS);
-    for (i = 0; i < s->channels; i ++) {
-        qemu_put_betl(f, s->chan[i].descr);
-        qemu_put_betl(f, s->chan[i].src);
-        qemu_put_betl(f, s->chan[i].dest);
-        qemu_put_be32s(f, &s->chan[i].cmd);
-        qemu_put_be32s(f, &s->chan[i].state);
-        qemu_put_be32(f, s->chan[i].request);
-    };
-}
+static void pxa2xx_dma_request(void *opaque, int req_num, int on);
 
-static int pxa2xx_dma_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
-    int i;
-
-    if (qemu_get_be32(f) != s->channels)
-        return -EINVAL;
-
-    qemu_get_be32s(f, &s->stopintr);
-    qemu_get_be32s(f, &s->eorintr);
-    qemu_get_be32s(f, &s->rasintr);
-    qemu_get_be32s(f, &s->startintr);
-    qemu_get_be32s(f, &s->endintr);
-    qemu_get_be32s(f, &s->align);
-    qemu_get_be32s(f, &s->pio);
-
-    qemu_get_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS);
-    for (i = 0; i < s->channels; i ++) {
-        s->chan[i].descr = qemu_get_betl(f);
-        s->chan[i].src = qemu_get_betl(f);
-        s->chan[i].dest = qemu_get_betl(f);
-        qemu_get_be32s(f, &s->chan[i].cmd);
-        qemu_get_be32s(f, &s->chan[i].state);
-        s->chan[i].request = qemu_get_be32(f);
-    };
-
-    return 0;
-}
-
-static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
-                qemu_irq irq, int channels)
+static int pxa2xx_dma_init(SysBusDevice *dev)
 {
     int i, iomemtype;
     PXA2xxDMAState *s;
-    s = (PXA2xxDMAState *)
-            qemu_mallocz(sizeof(PXA2xxDMAState));
+    s = FROM_SYSBUS(PXA2xxDMAState, dev);
+
+    if (s->channels <= 0) {
+        return -1;
+    }
 
-    s->channels = channels;
     s->chan = qemu_mallocz(sizeof(PXA2xxDMAChannel) * s->channels);
-    s->irq = irq;
-    s->req = qemu_mallocz(sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
     memset(s->chan, 0, sizeof(PXA2xxDMAChannel) * s->channels);
     for (i = 0; i < s->channels; i ++)
@@ -498,29 +446,47 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
 
     memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
+    qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
+
     iomemtype = cpu_register_io_memory(pxa2xx_dma_readfn,
                     pxa2xx_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00010000, iomemtype);
+    sysbus_init_mmio(dev, 0x00010000, iomemtype);
+    sysbus_init_irq(dev, &s->irq);
 
-    register_savevm(NULL, "pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
-
-    return s;
+    return 0;
 }
 
-PXA2xxDMAState *pxa27x_dma_init(target_phys_addr_t base,
-                qemu_irq irq)
+DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq)
 {
-    return pxa2xx_dma_init(base, irq, PXA27X_DMA_NUM_CHANNELS);
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "pxa2xx-dma");
+    qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
 }
 
-PXA2xxDMAState *pxa255_dma_init(target_phys_addr_t base,
-                qemu_irq irq)
+DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq)
 {
-    return pxa2xx_dma_init(base, irq, PXA255_DMA_NUM_CHANNELS);
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "pxa2xx-dma");
+    qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
 }
 
-void pxa2xx_dma_request(PXA2xxDMAState *s, int req_num, int on)
+static void pxa2xx_dma_request(void *opaque, int req_num, int on)
 {
+    PXA2xxDMAState *s = opaque;
     int ch;
     if (req_num < 0 || req_num >= PXA2XX_DMA_NUM_REQUESTS)
         hw_error("%s: Bad DMA request %i\n", __FUNCTION__, req_num);
@@ -542,3 +508,63 @@ void pxa2xx_dma_request(PXA2xxDMAState *s, int req_num, int on)
         pxa2xx_dma_update(s, ch);
     }
 }
+
+static bool is_version_0(void *opaque, int version_id)
+{
+    return version_id == 0;
+}
+
+static VMStateDescription vmstate_pxa2xx_dma_chan = {
+    .name = "pxa2xx_dma_chan",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINTTL(descr, PXA2xxDMAChannel),
+        VMSTATE_UINTTL(src, PXA2xxDMAChannel),
+        VMSTATE_UINTTL(dest, PXA2xxDMAChannel),
+        VMSTATE_UINT32(cmd, PXA2xxDMAChannel),
+        VMSTATE_UINT32(state, PXA2xxDMAChannel),
+        VMSTATE_INT32(request, PXA2xxDMAChannel),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static VMStateDescription vmstate_pxa2xx_dma = {
+    .name = "pxa2xx_dma",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UNUSED_TEST(is_version_0, 4),
+        VMSTATE_UINT32(stopintr, PXA2xxDMAState),
+        VMSTATE_UINT32(eorintr, PXA2xxDMAState),
+        VMSTATE_UINT32(rasintr, PXA2xxDMAState),
+        VMSTATE_UINT32(startintr, PXA2xxDMAState),
+        VMSTATE_UINT32(endintr, PXA2xxDMAState),
+        VMSTATE_UINT32(align, PXA2xxDMAState),
+        VMSTATE_UINT32(pio, PXA2xxDMAState),
+        VMSTATE_BUFFER(req, PXA2xxDMAState),
+        VMSTATE_STRUCT_VARRAY_POINTER_INT32(chan, PXA2xxDMAState, channels,
+                vmstate_pxa2xx_dma_chan, PXA2xxDMAChannel),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo pxa2xx_dma_info = {
+    .init       = pxa2xx_dma_init,
+    .qdev.name  = "pxa2xx-dma",
+    .qdev.desc  = "PXA2xx DMA controller",
+    .qdev.size  = sizeof(PXA2xxDMAState),
+    .qdev.vmsd  = &vmstate_pxa2xx_dma,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("channels", PXA2xxDMAState, channels, -1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void pxa2xx_dma_register(void)
+{
+    sysbus_register_withprop(&pxa2xx_dma_info);
+}
+device_init(pxa2xx_dma_register);
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index 24d409d..d86f735 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -10,10 +10,12 @@
 #include "hw.h"
 #include "pxa.h"
 #include "sd.h"
+#include "qdev.h"
 
 struct PXA2xxMMCIState {
     qemu_irq irq;
-    void *dma;
+    qemu_irq rx_dma;
+    qemu_irq tx_dma;
 
     SDState *card;
 
@@ -102,10 +104,8 @@ static void pxa2xx_mmci_int_update(PXA2xxMMCIState *s)
     if (s->cmdat & CMDAT_DMA_EN) {
         mask |= INT_RXFIFO_REQ | INT_TXFIFO_REQ;
 
-        pxa2xx_dma_request(s->dma,
-                        PXA2XX_RX_RQ_MMCI, !!(s->intreq & INT_RXFIFO_REQ));
-        pxa2xx_dma_request(s->dma,
-                        PXA2XX_TX_RQ_MMCI, !!(s->intreq & INT_TXFIFO_REQ));
+        qemu_set_irq(s->rx_dma, !!(s->intreq & INT_RXFIFO_REQ));
+        qemu_set_irq(s->tx_dma, !!(s->intreq & INT_TXFIFO_REQ));
     }
 
     qemu_set_irq(s->irq, !!(s->intreq & ~mask));
@@ -518,14 +518,16 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
-                BlockDriverState *bd, qemu_irq irq, void *dma)
+                BlockDriverState *bd, qemu_irq irq,
+                qemu_irq rx_dma, qemu_irq tx_dma)
 {
     int iomemtype;
     PXA2xxMMCIState *s;
 
     s = (PXA2xxMMCIState *) qemu_mallocz(sizeof(PXA2xxMMCIState));
     s->irq = irq;
-    s->dma = dma;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
 
     iomemtype = cpu_register_io_memory(pxa2xx_mmci_readfn,
                     pxa2xx_mmci_writefn, s, DEVICE_NATIVE_ENDIAN);
commit 47188700a45166b49f1579f3efeab72ae2045f7a
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Sun Feb 20 16:50:35 2011 +0300

    vmstate: move VMSTATE_PCIE_AER_ERRS to hw/hw.h
    
    VMSTATE_PCIE_AER_ERRS is indeed useful for other emulation drivers.
    Move it to hw/hw.h under the name of VMSTATE_STRUCT_VARRAY_POINTER_UINT16.
    Also add VMSTATE_STRUCT_VARRAY_POINTER_INT32 which is more or less
    the same as _UINT16 macro, except the fact it uses int32_t internally.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/hw.h b/hw/hw.h
index f35b579..4e2d592 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -496,6 +496,26 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = offsetof(_state, _field),                          \
 }
 
+#define VMSTATE_STRUCT_VARRAY_POINTER_INT32(_field, _state, _field_num, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = 0,                                                 \
+    .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
+    .size       = sizeof(_type),                                     \
+    .vmsd       = &(_vmsd),                                          \
+    .flags      = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT,       \
+    .offset     = vmstate_offset_pointer(_state, _field, _type),     \
+}
+
+#define VMSTATE_STRUCT_VARRAY_POINTER_UINT16(_field, _state, _field_num, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = 0,                                                 \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
+    .size       = sizeof(_type),                                     \
+    .vmsd       = &(_vmsd),                                          \
+    .flags      = VMS_POINTER | VMS_VARRAY_UINT16 | VMS_STRUCT,      \
+    .offset     = vmstate_offset_pointer(_state, _field, _type),     \
+}
+
 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 6e653dd..0c4e8a5 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -785,16 +785,6 @@ static const VMStateDescription vmstate_pcie_aer_err = {
     }
 };
 
-#define VMSTATE_PCIE_AER_ERRS(_field, _state, _field_num, _vmsd, _type) { \
-    .name       = (stringify(_field)),                                    \
-    .version_id = 0,                                                      \
-    .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),     \
-    .size       = sizeof(_type),                                          \
-    .vmsd       = &(_vmsd),                                               \
-    .flags      = VMS_POINTER | VMS_VARRAY_UINT16 | VMS_STRUCT,           \
-    .offset     = vmstate_offset_pointer(_state, _field, _type),          \
-}
-
 const VMStateDescription vmstate_pcie_aer_log = {
     .name = "PCIE_AER_ERROR_LOG",
     .version_id = 1,
@@ -803,7 +793,7 @@ const VMStateDescription vmstate_pcie_aer_log = {
     .fields     = (VMStateField[]) {
         VMSTATE_UINT16(log_num, PCIEAERLog),
         VMSTATE_UINT16(log_max, PCIEAERLog),
-        VMSTATE_PCIE_AER_ERRS(log, PCIEAERLog, log_num,
+        VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
                               vmstate_pcie_aer_err, PCIEAERErr),
         VMSTATE_END_OF_LIST()
     }
commit ee2479d3e8fbf6d79813eb7744725ae0e14eaf58
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Sun Feb 20 16:50:36 2011 +0300

    pxa2xx_dma: drop unused pxa2xx_dma_handler_t/handler field
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index b512d34..92c3e1e 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -20,11 +20,7 @@ typedef struct {
     int request;
 } PXA2xxDMAChannel;
 
-/* Allow the DMA to be used as a PIC.  */
-typedef void (*pxa2xx_dma_handler_t)(void *opaque, int irq, int level);
-
 struct PXA2xxDMAState {
-    pxa2xx_dma_handler_t handler;
     qemu_irq irq;
 
     uint32_t stopintr;
@@ -494,7 +490,6 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
     s->channels = channels;
     s->chan = qemu_mallocz(sizeof(PXA2xxDMAChannel) * s->channels);
     s->irq = irq;
-    s->handler = (pxa2xx_dma_handler_t) pxa2xx_dma_request;
     s->req = qemu_mallocz(sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
     memset(s->chan, 0, sizeof(PXA2xxDMAChannel) * s->channels);
commit 5251d196aa712a28528fee5f93af3fe10a0b7f27
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Thu Mar 3 14:24:25 2011 +0100

    pxa2xx_timer: Store relevant irq line in each timer.

diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 3a50138..0fbd4a8 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -65,6 +65,7 @@ typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
 typedef struct {
     uint32_t value;
     int level;
+    qemu_irq irq;
     QEMUTimer *qtimer;
     int num;
     PXA2xxTimerInfo *info;
@@ -88,14 +89,12 @@ struct PXA2xxTimerInfo {
     uint64_t lastload;
     uint32_t freq;
     PXA2xxTimer0 timer[4];
-    qemu_irq irqs[5];
     uint32_t events;
     uint32_t irq_enabled;
     uint32_t reset3;
     uint32_t snapshot;
 
     PXA2xxTimer4 tm4[8];
-    qemu_irq irq4;
 };
 
 #define PXA2XX_TIMER_HAVE_TM4	0
@@ -282,7 +281,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
         for (i = 0; i < 4; i ++, value >>= 1) {
             if (s->timer[i].level && (value & 1)) {
                 s->timer[i].level = 0;
-                qemu_irq_lower(s->irqs[i]);
+                qemu_irq_lower(s->timer[i].irq);
             }
         }
         if (pxa2xx_timer_has_tm4(s)) {
@@ -290,7 +289,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                 if (s->tm4[i].tm.level && (value & 1))
                     s->tm4[i].tm.level = 0;
             if (!(s->events & 0xff0))
-                qemu_irq_lower(s->irq4);
+                qemu_irq_lower(s->tm4->tm.irq);
         }
         break;
     case OWER:	/* XXX: Reset on OSMR3 match? */
@@ -353,7 +352,7 @@ static void pxa2xx_timer_tick(void *opaque)
     if (i->irq_enabled & (1 << t->num)) {
         t->level = 1;
         i->events |= 1 << t->num;
-        qemu_irq_raise(t->num < 4 ? i->irqs[t->num] : i->irq4);
+        qemu_irq_raise(t->irq);
     }
 
     if (t->num == 3)
@@ -396,6 +395,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
     int i;
     int iomemtype;
     PXA2xxTimerInfo *s;
+    qemu_irq irq4;
 
     s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
     s->irq_enabled = 0;
@@ -406,7 +406,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
 
     for (i = 0; i < 4; i ++) {
         s->timer[i].value = 0;
-        sysbus_init_irq(dev, &s->irqs[i]);
+        sysbus_init_irq(dev, &s->timer[i].irq);
         s->timer[i].info = s;
         s->timer[i].num = i;
         s->timer[i].level = 0;
@@ -414,7 +414,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
                         pxa2xx_timer_tick, &s->timer[i]);
     }
     if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
-        sysbus_init_irq(dev, &s->irq4);
+        sysbus_init_irq(dev, &irq4);
 
         for (i = 0; i < 8; i ++) {
             s->tm4[i].tm.value = 0;
@@ -425,6 +425,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev)
             s->tm4[i].control = 0x0;
             s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
                         pxa2xx_timer_tick4, &s->tm4[i]);
+            s->tm4[i].tm.irq = irq4;
         }
     }
 
commit 797e9542f56b37632fddbfeb810d4a9ed1fc55ab
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Thu Mar 3 14:14:44 2011 +0100

    pxa2xx_timer: switch to using qdev/vmstate
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 5874116..7d7f49e 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -65,10 +65,6 @@
 /* pxa2xx_pic.c */
 DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
 
-/* pxa2xx_timer.c */
-void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic);
-void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic);
-
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
                 CPUState *env, DeviceState *pic, int lines);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 6ff8131..7c31fab 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2100,7 +2100,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     s->dma = pxa27x_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa27x_timer_init(0x40a00000, s->pic);
+    sysbus_create_varargs("pxa27x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
+                    NULL);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
 
@@ -2229,7 +2235,12 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     s->dma = pxa255_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa25x_timer_init(0x40a00000, s->pic);
+    sysbus_create_varargs("pxa25x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    NULL);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
 
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 08141a2..3a50138 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -10,8 +10,8 @@
 #include "hw.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
-#include "qdev.h"
 #include "pxa.h"
+#include "sysbus.h"
 
 #define OSMR0	0x00
 #define OSMR1	0x04
@@ -60,13 +60,14 @@ static int pxa2xx_timer4_freq[8] = {
     [5 ... 7] = 0,
 };
 
+typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
+
 typedef struct {
     uint32_t value;
     int level;
-    qemu_irq irq;
     QEMUTimer *qtimer;
     int num;
-    void *info;
+    PXA2xxTimerInfo *info;
 } PXA2xxTimer0;
 
 typedef struct {
@@ -78,18 +79,31 @@ typedef struct {
     uint32_t control;
 } PXA2xxTimer4;
 
-typedef struct {
+struct PXA2xxTimerInfo {
+    SysBusDevice busdev;
+    uint32_t flags;
+
     int32_t clock;
     int32_t oldclock;
     uint64_t lastload;
     uint32_t freq;
     PXA2xxTimer0 timer[4];
-    PXA2xxTimer4 *tm4;
+    qemu_irq irqs[5];
     uint32_t events;
     uint32_t irq_enabled;
     uint32_t reset3;
     uint32_t snapshot;
-} PXA2xxTimerInfo;
+
+    PXA2xxTimer4 tm4[8];
+    qemu_irq irq4;
+};
+
+#define PXA2XX_TIMER_HAVE_TM4	0
+
+static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
+{
+    return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
+}
 
 static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
 {
@@ -154,7 +168,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
     case OSMR6:  tm ++;
     case OSMR5:  tm ++;
     case OSMR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         return s->tm4[tm].tm.value;
     case OSCR:
@@ -168,7 +182,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
     case OSCR6:  tm ++;
     case OSCR5:  tm ++;
     case OSCR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
 
         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
@@ -199,7 +213,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
     case OMCR6:  tm ++;
     case OMCR5:  tm ++;
     case OMCR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         return s->tm4[tm].control;
     case OSNR:
@@ -234,7 +248,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     case OSMR6:  tm ++;
     case OSMR5:  tm ++;
     case OSMR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].tm.value = value;
         pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
@@ -253,7 +267,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     case OSCR6:  tm ++;
     case OSCR5:  tm ++;
     case OSCR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].oldclock = s->tm4[tm].clock;
         s->tm4[tm].lastload = qemu_get_clock(vm_clock);
@@ -268,15 +282,15 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
         for (i = 0; i < 4; i ++, value >>= 1) {
             if (s->timer[i].level && (value & 1)) {
                 s->timer[i].level = 0;
-                qemu_irq_lower(s->timer[i].irq);
+                qemu_irq_lower(s->irqs[i]);
             }
         }
-        if (s->tm4) {
+        if (pxa2xx_timer_has_tm4(s)) {
             for (i = 0; i < 8; i ++, value >>= 1)
                 if (s->tm4[i].tm.level && (value & 1))
                     s->tm4[i].tm.level = 0;
             if (!(s->events & 0xff0))
-                qemu_irq_lower(s->tm4->tm.irq);
+                qemu_irq_lower(s->irq4);
         }
         break;
     case OWER:	/* XXX: Reset on OSMR3 match? */
@@ -286,7 +300,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     case OMCR6:  tm ++;
     case OMCR5:  tm ++;
     case OMCR4:
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].control = value & 0x0ff;
         /* XXX Stop if running (shouldn't happen) */
@@ -301,7 +315,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
     case OMCR10: tm ++;
     case OMCR9:  tm ++;
     case OMCR8:  tm += 4;
-        if (!s->tm4)
+        if (!pxa2xx_timer_has_tm4(s))
             goto badreg;
         s->tm4[tm].control = value & 0x3ff;
         /* XXX Stop if running (shouldn't happen) */
@@ -334,12 +348,12 @@ static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
 static void pxa2xx_timer_tick(void *opaque)
 {
     PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
-    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->info;
+    PXA2xxTimerInfo *i = t->info;
 
     if (i->irq_enabled & (1 << t->num)) {
         t->level = 1;
         i->events |= 1 << t->num;
-        qemu_irq_raise(t->irq);
+        qemu_irq_raise(t->num < 4 ? i->irqs[t->num] : i->irq4);
     }
 
     if (t->num == 3)
@@ -361,81 +375,29 @@ static void pxa2xx_timer_tick4(void *opaque)
         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
 }
 
-static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
-    int i;
-
-    qemu_put_be32s(f, (uint32_t *) &s->clock);
-    qemu_put_be32s(f, (uint32_t *) &s->oldclock);
-    qemu_put_be64s(f, &s->lastload);
-
-    for (i = 0; i < 4; i ++) {
-        qemu_put_be32s(f, &s->timer[i].value);
-        qemu_put_be32(f, s->timer[i].level);
-    }
-    if (s->tm4)
-        for (i = 0; i < 8; i ++) {
-            qemu_put_be32s(f, &s->tm4[i].tm.value);
-            qemu_put_be32(f, s->tm4[i].tm.level);
-            qemu_put_sbe32s(f, &s->tm4[i].oldclock);
-            qemu_put_sbe32s(f, &s->tm4[i].clock);
-            qemu_put_be64s(f, &s->tm4[i].lastload);
-            qemu_put_be32s(f, &s->tm4[i].freq);
-            qemu_put_be32s(f, &s->tm4[i].control);
-        }
-
-    qemu_put_be32s(f, &s->events);
-    qemu_put_be32s(f, &s->irq_enabled);
-    qemu_put_be32s(f, &s->reset3);
-    qemu_put_be32s(f, &s->snapshot);
-}
-
-static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
+static int pxa25x_timer_post_load(void *opaque, int version_id)
 {
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int64_t now;
     int i;
 
-    qemu_get_be32s(f, (uint32_t *) &s->clock);
-    qemu_get_be32s(f, (uint32_t *) &s->oldclock);
-    qemu_get_be64s(f, &s->lastload);
-
     now = qemu_get_clock(vm_clock);
-    for (i = 0; i < 4; i ++) {
-        qemu_get_be32s(f, &s->timer[i].value);
-        s->timer[i].level = qemu_get_be32(f);
-    }
     pxa2xx_timer_update(s, now);
 
-    if (s->tm4)
-        for (i = 0; i < 8; i ++) {
-            qemu_get_be32s(f, &s->tm4[i].tm.value);
-            s->tm4[i].tm.level = qemu_get_be32(f);
-            qemu_get_sbe32s(f, &s->tm4[i].oldclock);
-            qemu_get_sbe32s(f, &s->tm4[i].clock);
-            qemu_get_be64s(f, &s->tm4[i].lastload);
-            qemu_get_be32s(f, &s->tm4[i].freq);
-            qemu_get_be32s(f, &s->tm4[i].control);
+    if (pxa2xx_timer_has_tm4(s))
+        for (i = 0; i < 8; i ++)
             pxa2xx_timer_update4(s, now, i);
-        }
-
-    qemu_get_be32s(f, &s->events);
-    qemu_get_be32s(f, &s->irq_enabled);
-    qemu_get_be32s(f, &s->reset3);
-    qemu_get_be32s(f, &s->snapshot);
 
     return 0;
 }
 
-static PXA2xxTimerInfo *pxa2xx_timer_init(target_phys_addr_t base,
-                DeviceState *pic)
+static int pxa2xx_timer_init(SysBusDevice *dev)
 {
     int i;
     int iomemtype;
     PXA2xxTimerInfo *s;
 
-    s = (PXA2xxTimerInfo *) qemu_mallocz(sizeof(PXA2xxTimerInfo));
+    s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
     s->irq_enabled = 0;
     s->oldclock = 0;
     s->clock = 0;
@@ -444,47 +406,123 @@ static PXA2xxTimerInfo *pxa2xx_timer_init(target_phys_addr_t base,
 
     for (i = 0; i < 4; i ++) {
         s->timer[i].value = 0;
-        s->timer[i].irq = qdev_get_gpio_in(pic, PXA2XX_PIC_OST_0 + i);
+        sysbus_init_irq(dev, &s->irqs[i]);
         s->timer[i].info = s;
         s->timer[i].num = i;
         s->timer[i].level = 0;
         s->timer[i].qtimer = qemu_new_timer(vm_clock,
                         pxa2xx_timer_tick, &s->timer[i]);
     }
+    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
+        sysbus_init_irq(dev, &s->irq4);
+
+        for (i = 0; i < 8; i ++) {
+            s->tm4[i].tm.value = 0;
+            s->tm4[i].tm.info = s;
+            s->tm4[i].tm.num = i + 4;
+            s->tm4[i].tm.level = 0;
+            s->tm4[i].freq = 0;
+            s->tm4[i].control = 0x0;
+            s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
+                        pxa2xx_timer_tick4, &s->tm4[i]);
+        }
+    }
 
     iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
                     pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    sysbus_init_mmio(dev, 0x00001000, iomemtype);
 
-    register_savevm(NULL, "pxa2xx_timer", 0, 0,
-                    pxa2xx_timer_save, pxa2xx_timer_load, s);
-
-    return s;
+    return 0;
 }
 
-void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic)
+static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
+    .name = "pxa2xx_timer0",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(value, PXA2xxTimer0),
+        VMSTATE_INT32(level, PXA2xxTimer0),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
+    .name = "pxa2xx_timer4",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
+                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
+        VMSTATE_INT32(oldclock, PXA2xxTimer4),
+        VMSTATE_INT32(clock, PXA2xxTimer4),
+        VMSTATE_UINT64(lastload, PXA2xxTimer4),
+        VMSTATE_UINT32(freq, PXA2xxTimer4),
+        VMSTATE_UINT32(control, PXA2xxTimer4),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
 {
-    PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic);
-    s->freq = PXA25X_FREQ;
-    s->tm4 = NULL;
+    return pxa2xx_timer_has_tm4(opaque);
 }
 
-void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic)
-{
-    PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic);
-    int i;
-    s->freq = PXA27X_FREQ;
-    s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 *
-                    sizeof(PXA2xxTimer4));
-    for (i = 0; i < 8; i ++) {
-        s->tm4[i].tm.value = 0;
-        s->tm4[i].tm.irq = qdev_get_gpio_in(pic, PXA27X_PIC_OST_4_11);
-        s->tm4[i].tm.info = s;
-        s->tm4[i].tm.num = i + 4;
-        s->tm4[i].tm.level = 0;
-        s->tm4[i].freq = 0;
-        s->tm4[i].control = 0x0;
-        s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
-                        pxa2xx_timer_tick4, &s->tm4[i]);
+static const VMStateDescription vmstate_pxa2xx_timer_regs = {
+    .name = "pxa2xx_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = pxa25x_timer_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(clock, PXA2xxTimerInfo),
+        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
+        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
+        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
+                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
+        VMSTATE_UINT32(events, PXA2xxTimerInfo),
+        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
+        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
+        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
+        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
+                        pxa2xx_timer_has_tm4_test, 0,
+                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
+        VMSTATE_END_OF_LIST(),
     }
-}
+};
+
+static SysBusDeviceInfo pxa25x_timer_dev_info = {
+    .init       = pxa2xx_timer_init,
+    .qdev.name  = "pxa25x-timer",
+    .qdev.desc  = "PXA25x timer",
+    .qdev.size  = sizeof(PXA2xxTimerInfo),
+    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
+        DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
+                        PXA2XX_TIMER_HAVE_TM4, false),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo pxa27x_timer_dev_info = {
+    .init       = pxa2xx_timer_init,
+    .qdev.name  = "pxa27x-timer",
+    .qdev.desc  = "PXA27x timer",
+    .qdev.size  = sizeof(PXA2xxTimerInfo),
+    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
+        DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
+                        PXA2XX_TIMER_HAVE_TM4, true),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void pxa2xx_timer_register(void)
+{
+    sysbus_register_withprop(&pxa25x_timer_dev_info);
+    sysbus_register_withprop(&pxa27x_timer_dev_info);
+};
+device_init(pxa2xx_timer_register);
commit d353eb43cffc4e8f44f3acba0d04743ba3f4aca1
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Sun Feb 20 16:50:33 2011 +0300

    pxa2xx_timer: change info struct name to comply with guidelines
    
    It should be PXA2xxTimerInfo, not pxa2xx_timer_info. Replace all
    occurences of old name with the new one.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 7ab2cc3..08141a2 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -89,11 +89,11 @@ typedef struct {
     uint32_t irq_enabled;
     uint32_t reset3;
     uint32_t snapshot;
-} pxa2xx_timer_info;
+} PXA2xxTimerInfo;
 
 static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
 {
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int i;
     uint32_t now_vm;
     uint64_t new_qemu;
@@ -110,7 +110,7 @@ static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
 
 static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
 {
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     uint32_t now_vm;
     uint64_t new_qemu;
     static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
@@ -137,7 +137,7 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
 
 static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 {
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int tm = 0;
 
     switch (offset) {
@@ -216,7 +216,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                 uint32_t value)
 {
     int i, tm = 0;
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 
     switch (offset) {
     case OSMR3:  tm ++;
@@ -334,7 +334,7 @@ static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
 static void pxa2xx_timer_tick(void *opaque)
 {
     PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
-    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
+    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->info;
 
     if (i->irq_enabled & (1 << t->num)) {
         t->level = 1;
@@ -352,7 +352,7 @@ static void pxa2xx_timer_tick(void *opaque)
 static void pxa2xx_timer_tick4(void *opaque)
 {
     PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
-    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
+    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
 
     pxa2xx_timer_tick(&t->tm);
     if (t->control & (1 << 3))
@@ -363,7 +363,7 @@ static void pxa2xx_timer_tick4(void *opaque)
 
 static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
 {
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int i;
 
     qemu_put_be32s(f, (uint32_t *) &s->clock);
@@ -393,7 +393,7 @@ static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
 
 static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
 {
-    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
     int64_t now;
     int i;
 
@@ -428,14 +428,14 @@ static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
+static PXA2xxTimerInfo *pxa2xx_timer_init(target_phys_addr_t base,
                 DeviceState *pic)
 {
     int i;
     int iomemtype;
-    pxa2xx_timer_info *s;
+    PXA2xxTimerInfo *s;
 
-    s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
+    s = (PXA2xxTimerInfo *) qemu_mallocz(sizeof(PXA2xxTimerInfo));
     s->irq_enabled = 0;
     s->oldclock = 0;
     s->clock = 0;
@@ -464,14 +464,14 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
 
 void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
+    PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic);
     s->freq = PXA25X_FREQ;
     s->tm4 = NULL;
 }
 
 void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
+    PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic);
     int i;
     s->freq = PXA27X_FREQ;
     s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 *
commit 0c69aa703c543ae4e287416590ccd9928f75d32b
Author: Andrzej Zaborowski <andrew.zaborowski at intel.com>
Date:   Thu Mar 3 03:43:40 2011 +0100

    pxa2xx_pic: Set base address for sysbus device.
    
    Thid device's registration was broken since
    e1f8c729fa890c67bb4532f22c22ace6fb0e1aaf, this should fix it.

diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 308d052..86c0ee6 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -268,6 +268,8 @@ DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 
     qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
     /* Enable IC memory-mapped registers access.  */
     iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
                     pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
commit 13801f32f6bd74eae9bb2fcfaee75c6656f7f73e
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Thu Mar 3 03:34:01 2011 +0100

    vmstate: add VMSTATE_STRUCT_ARRAY_TEST
    
    This is a _TEST variant of VMSTATE_STRUCT_ARRAY, necessary e.g.
    for future patch changing pxa2xx_timer to use vmstate.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/hw.h b/hw/hw.h
index 5e24329..f35b579 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -475,14 +475,15 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
-#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) { \
-    .name       = (stringify(_field)),                               \
-    .num        = (_num),                                            \
-    .version_id = (_version),                                        \
-    .vmsd       = &(_vmsd),                                          \
-    .size       = sizeof(_type),                                     \
-    .flags      = VMS_STRUCT|VMS_ARRAY,                              \
-    .offset     = vmstate_offset_array(_state, _field, _type, _num), \
+#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \
+    .name         = (stringify(_field)),                             \
+    .num          = (_num),                                          \
+    .field_exists = (_test),                                         \
+    .version_id   = (_version),                                      \
+    .vmsd         = &(_vmsd),                                        \
+    .size         = sizeof(_type),                                   \
+    .flags        = VMS_STRUCT|VMS_ARRAY,                            \
+    .offset       = vmstate_offset_array(_state, _field, _type, _num),\
 }
 
 #define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
@@ -625,6 +626,10 @@ extern const VMStateDescription vmstate_usb_device;
 #define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type)          \
     VMSTATE_STRUCT_POINTER_TEST(_field, _state, NULL, _vmsd, _type)
 
+#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \
+    VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version,   \
+            _vmsd, _type)
+
 #define VMSTATE_BOOL_V(_f, _s, _v)                                    \
     VMSTATE_SINGLE(_f, _s, _v, vmstate_info_bool, bool)
 
commit ed02c54d1fd5d35c06e62e3dae84ee5bb90097ef
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Mar 1 22:17:52 2011 +0100

    microblaze: Correct copy+paste:o in defconfigs
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/default-configs/microblazeel-linux-user.mak b/default-configs/microblazeel-linux-user.mak
index 566fdc0..378c6dd 100644
--- a/default-configs/microblazeel-linux-user.mak
+++ b/default-configs/microblazeel-linux-user.mak
@@ -1 +1 @@
-# Default configuration for microblaze-linux-user
+# Default configuration for microblazeel-linux-user
diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak
index 4399b8b..ddc6bf4 100644
--- a/default-configs/microblazeel-softmmu.mak
+++ b/default-configs/microblazeel-softmmu.mak
@@ -1,4 +1,4 @@
-# Default configuration for microblaze-softmmu
+# Default configuration for microblazeel-softmmu
 
 CONFIG_PTIMER=y
 CONFIG_PFLASH_CFI01=y
commit 417131fb9ad3f6dd7177a338cc5f143dec4d75f0
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Feb 25 16:30:20 2011 -0600

    HACKING: Update status of format checking
    
    Hopefully all functions with printf like arguments now use format checking.
    
    This was tested with default build configuration on linux
    and windows hosts (including some cross compilations),
    so chances are good that there remain few (if any) functions
    without format checking.
    
    Therefore the last comment in HACKING is no longer valid but misleading.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/HACKING b/HACKING
index 6ba9d7e..3af53fd 100644
--- a/HACKING
+++ b/HACKING
@@ -120,6 +120,3 @@ gcc's printf attribute directive in the prototype.
 This makes it so gcc's -Wformat and -Wformat-security options can do
 their jobs and cross-check format strings with the number and types
 of arguments.
-
-Currently many functions in QEMU are not following this rule but
-patches to add the attribute would be very much appreciated.
commit c53af37f375ce9c4999ff451c51173bdc1167e67
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 25 22:54:53 2011 +0100

    vnc: fix a memory leak in threaded vnc server
    
    VncJobQueue's buffer is intended to be used for
    as the output buffer for all operations in this queue,
    but unfortunatly.
    
    vnc_async_encoding_start() is in charge of setting this
    buffer as the current output buffer, but
    vnc_async_encoding_end() was not writting the changes back
    to VncJobQueue, resulting in a big and ugly memleak.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index 1d4c5e7..f596247 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -186,6 +186,8 @@ static void vnc_async_encoding_end(VncState *orig, VncState *local)
     orig->hextile = local->hextile;
     orig->zrle = local->zrle;
     orig->lossy_rect = local->lossy_rect;
+
+    queue->buffer = local->output;
 }
 
 static int vnc_worker_thread_loop(VncJobQueue *queue)
commit 30faaf7073dd51b9e06589d7886696a3f13f201c
Author: Tristan Gingold <gingold at adacore.com>
Date:   Fri Feb 18 14:17:16 2011 +0100

    Use sigwait instead of sigwaitinfo.
    
    Fix compilation failure on Darwin.
    
    Signed-off-by: Tristan Gingold <gingold at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/compatfd.c b/compatfd.c
index a7cebc4..bd377c4 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -26,45 +26,45 @@ struct sigfd_compat_info
 static void *sigwait_compat(void *opaque)
 {
     struct sigfd_compat_info *info = opaque;
-    int err;
     sigset_t all;
 
     sigfillset(&all);
     sigprocmask(SIG_BLOCK, &all, NULL);
 
-    do {
-        siginfo_t siginfo;
+    while (1) {
+        int sig;
+        int err;
 
-        err = sigwaitinfo(&info->mask, &siginfo);
-        if (err == -1 && errno == EINTR) {
-            err = 0;
-            continue;
-        }
-
-        if (err > 0) {
-            char buffer[128];
+        err = sigwait(&info->mask, &sig);
+        if (err != 0) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                return NULL;
+            }
+        } else {
+            struct qemu_signalfd_siginfo buffer;
             size_t offset = 0;
 
-            memcpy(buffer, &err, sizeof(err));
+            memset(&buffer, 0, sizeof(buffer));
+            buffer.ssi_signo = sig;
+
             while (offset < sizeof(buffer)) {
                 ssize_t len;
 
-                len = write(info->fd, buffer + offset,
+                len = write(info->fd, (char *)&buffer + offset,
                             sizeof(buffer) - offset);
                 if (len == -1 && errno == EINTR)
                     continue;
 
                 if (len <= 0) {
-                    err = -1;
-                    break;
+                    return NULL;
                 }
 
                 offset += len;
             }
         }
-    } while (err >= 0);
-
-    return NULL;
+    }
 }
 
 static int qemu_signalfd_compat(const sigset_t *mask)
commit 84803d7a27ef2e83c9b870ebd48e249696909e98
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Feb 25 17:21:22 2011 +0000

    bitops: fix error on OpenBSD and mingw32
    
    Fix this error:
      CC    bitops.o
    In file included from /src/qemu/bitops.c:14:
    /src/qemu/bitops.h:69: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'unsigned'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/bitops.h b/bitops.h
index e2b9df3..07d1a06 100644
--- a/bitops.h
+++ b/bitops.h
@@ -66,7 +66,7 @@ static unsigned long bitops_ffsl(unsigned long word)
  *
  * Undefined if no set bit exists, so code should check against 0 first.
  */
-static __always_inline unsigned long bitops_flsl(unsigned long word)
+static inline unsigned long bitops_flsl(unsigned long word)
 {
 	int num = BITS_PER_LONG - 1;
 
commit 04483e150d412f5861a00c30581df7ba90a816e7
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Thu Feb 24 23:47:08 2011 +0100

    bitops: fix test_and_change_bit()
    
    ./bitops.h:192: warning: ‘old’ is used uninitialized in this function
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/bitops.h b/bitops.h
index ae7bcb1..e2b9df3 100644
--- a/bitops.h
+++ b/bitops.h
@@ -187,7 +187,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
-	unsigned long old;
+	unsigned long old = *p;
 
 	*p = old ^ mask;
 	return (old & mask) != 0;
commit 89d2d3af518879ddfca367e56627229a09e90352
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Feb 23 19:40:14 2011 +0100

    slirp: Remove some type casts caused by bad declaration of x.tp_buf
    
    x.tp_buf was declared as a uint8_t array, but always used as
    a char array (which needed a lot of type casts).
    
    The patch includes these changes:
    
    * Fix declaration of x.tp_buf and remove all type casts.
    
    * Use offsetof() to get the offset of x.tp_buf.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/slirp/tftp.c b/slirp/tftp.c
index 1821648..8055ccc 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -136,9 +136,9 @@ static int tftp_send_oack(struct tftp_session *spt,
     m->m_data += sizeof(struct udpiphdr);
 
     tp->tp_op = htons(TFTP_OACK);
-    n += snprintf((char *)tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s",
+    n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s",
                   key) + 1;
-    n += snprintf((char *)tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u",
+    n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u",
                   value) + 1;
 
     saddr.sin_addr = recv_tp->ip.ip_dst;
@@ -283,7 +283,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
 
   /* skip header fields */
   k = 0;
-  pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
+  pktlen -= offsetof(struct tftp_t, x.tp_buf);
 
   /* prepend tftp_prefix */
   prefix_len = strlen(slirp->tftp_prefix);
@@ -299,7 +299,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
     }
-    req_fname[k] = (char)tp->x.tp_buf[k];
+    req_fname[k] = tp->x.tp_buf[k];
     if (req_fname[k++] == '\0') {
       break;
     }
@@ -311,7 +311,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
     return;
   }
 
-  if (strcasecmp((const char *)&tp->x.tp_buf[k], "octet") != 0) {
+  if (strcasecmp(&tp->x.tp_buf[k], "octet") != 0) {
       tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
       return;
   }
@@ -340,7 +340,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
   while (k < pktlen) {
       const char *key, *value;
 
-      key = (const char *)&tp->x.tp_buf[k];
+      key = &tp->x.tp_buf[k];
       k += strlen(key) + 1;
 
       if (k >= pktlen) {
@@ -348,7 +348,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
 	  return;
       }
 
-      value = (const char *)&tp->x.tp_buf[k];
+      value = &tp->x.tp_buf[k];
       k += strlen(value) + 1;
 
       if (strcasecmp(key, "tsize") == 0) {
diff --git a/slirp/tftp.h b/slirp/tftp.h
index b9f0847..72e5e91 100644
--- a/slirp/tftp.h
+++ b/slirp/tftp.h
@@ -26,7 +26,7 @@ struct tftp_t {
       uint16_t tp_error_code;
       uint8_t tp_msg[512];
     } tp_error;
-    uint8_t tp_buf[512 + 2];
+    char tp_buf[512 + 2];
   } x;
 };
 
commit c3febae62b646b5bc7aa88b7cffa88160162a94e
Author: Pavel Dovgaluk <Pavel.Dovgaluk at ispras.ru>
Date:   Mon Feb 21 14:47:50 2011 +0300

    Fixing tap adapter for win32
    
       This fix allows connection of internal VLAN to the external TAP interface.
    If tap_win32_write function always returns 0, the TAP network interface
    in QEMU is disabled.
    
    Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/net/tap-win32.c b/net/tap-win32.c
index 081904e..596132e 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -480,7 +480,7 @@ static int tap_win32_write(tap_win32_overlapped_t *overlapped,
         }
     }
 
-    return 0;
+    return write_size;
 }
 
 static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
commit c7eb1f02edba91e3eec4682fa1adca877696d11d
Author: Pavel Dovgaluk <Pavel.Dovgaluk at ispras.ru>
Date:   Mon Feb 21 14:46:44 2011 +0300

    Fixing network over sockets implementation for win32
    
      MSDN includes the following in WSAEALREADY error description for connect()
    function: "To preserve backward compatibility, this error is reported as
    WSAEINVAL to Winsock applications that link to either Winsock.dll or
    Wsock32.dll". So check of this error code was added to allow network
    connections through the sockets in Windows.
    
    Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/net/socket.c b/net/socket.c
index 3182b37..7337f4f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -457,7 +457,7 @@ static int net_socket_connect_init(VLANState *vlan,
             } else if (err == EINPROGRESS) {
                 break;
 #ifdef _WIN32
-            } else if (err == WSAEALREADY) {
+            } else if (err == WSAEALREADY || err == WSAEINVAL) {
                 break;
 #endif
             } else {
commit e1f8c729fa890c67bb4532f22c22ace6fb0e1aaf
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Feb 25 12:13:38 2011 +0100

    pxa2xx_pic: update to use qdev
    
    Use qdev/sysbus framework to handle pxa2xx-pic. Instead of exposing IRQs
    via array, reference them via qdev_get_gpio_in().
    
    Patch has been modified by the committer.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/mainstone.c b/hw/mainstone.c
index aec8d34..4eabdb9 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -140,7 +140,7 @@ static void mainstone_common_init(ram_addr_t ram_size,
     }
 
     mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
-                    cpu->pic[PXA2XX_PIC_GPIO_0]);
+                    qdev_get_gpio_in(cpu->pic, PXA2XX_PIC_GPIO_0));
 
     /* setup keypad */
     printf("map addr %p\n", &map);
diff --git a/hw/pxa.h b/hw/pxa.h
index f73d33b..5874116 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -63,15 +63,15 @@
 # define PXA2XX_INTERNAL_SIZE	0x40000
 
 /* pxa2xx_pic.c */
-qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
 
 /* pxa2xx_timer.c */
-void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs);
-void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4);
+void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic);
+void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic);
 
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, qemu_irq *pic, int lines);
+                CPUState *env, DeviceState *pic, int lines);
 void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
 
 /* pxa2xx_dma.c */
@@ -125,7 +125,7 @@ typedef struct PXA2xxFIrState PXA2xxFIrState;
 
 typedef struct {
     CPUState *env;
-    qemu_irq *pic;
+    DeviceState *pic;
     qemu_irq reset;
     PXA2xxDMAState *dma;
     DeviceState *gpio;
@@ -180,6 +180,7 @@ typedef struct {
     QEMUTimer *rtc_swal1;
     QEMUTimer *rtc_swal2;
     QEMUTimer *rtc_pi;
+    qemu_irq rtc_irq;
 } PXA2xxState;
 
 struct PXA2xxI2SState {
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index dc595f3..6ff8131 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -888,7 +888,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
 
 static inline void pxa2xx_rtc_int_update(PXA2xxState *s)
 {
-    qemu_set_irq(s->pic[PXA2XX_PIC_RTCALARM], !!(s->rtsr & 0x2553));
+    qemu_set_irq(s->rtc_irq, !!(s->rtsr & 0x2553));
 }
 
 static void pxa2xx_rtc_hzupdate(PXA2xxState *s)
@@ -1197,6 +1197,8 @@ static void pxa2xx_rtc_init(PXA2xxState *s)
     s->rtc_swal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal1_tick, s);
     s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s);
     s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
+
+    s->rtc_irq = qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM);
 }
 
 static void pxa2xx_rtc_save(QEMUFile *f, void *opaque)
@@ -2095,10 +2097,10 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
-    s->dma = pxa27x_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
+    s->dma = pxa27x_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa27x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0],
-                    s->pic[PXA27X_PIC_OST_4_11]);
+    pxa27x_timer_init(0x40a00000, s->pic);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
 
@@ -2108,26 +2110,28 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
-                              s->pic[PXA2XX_PIC_MMC], s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), s->dma);
 
     for (i = 0; pxa270_serial[i].io_base; i ++)
         if (serial_hds[i])
 #ifdef TARGET_WORDS_BIGENDIAN
             serial_mm_init(pxa270_serial[i].io_base, 2,
-                           s->pic[pxa270_serial[i].irqn], 14857000/16,
-                           serial_hds[i], 1, 1);
+                            qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
+                            14857000 / 16, serial_hds[i], 1, 1);
 #else
             serial_mm_init(pxa270_serial[i].io_base, 2,
-                           s->pic[pxa270_serial[i].irqn], 14857000/16,
-                           serial_hds[i], 1, 0);
+                            qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
+                            14857000 / 16, serial_hds[i], 1, 0);
 #endif
         else
             break;
     if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
+        s->fir = pxa2xx_fir_init(0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
                         s->dma, serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD]);
+    s->lcd = pxa2xx_lcdc_init(0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
@@ -2159,13 +2163,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     for (i = 0; pxa27x_ssp[i].io_base; i ++) {
         DeviceState *dev;
         dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
-                                   s->pic[pxa27x_ssp[i].irqn]);
+                        qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
         s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
     }
 
     if (usb_enabled) {
         sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                             s->pic[PXA2XX_PIC_USBH1]);
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
     s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
@@ -2179,12 +2183,16 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
                     pxa2xx_rtc_load, s);
 
-    s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
-    s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
+    s->i2s = pxa2xx_i2s_init(0x40400000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S), s->dma);
 
-    s->kp = pxa27x_keypad_init(0x41500000, s->pic[PXA2XX_PIC_KEYPAD]);
+    s->kp = pxa27x_keypad_init(0x41500000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
 
     /* GPIO1 resets the processor */
     /* The handler can be overridden by board-specific code */
@@ -2218,9 +2226,10 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
-    s->dma = pxa255_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
+    s->dma = pxa255_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa25x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0]);
+    pxa25x_timer_init(0x40a00000, s->pic);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
 
@@ -2230,27 +2239,29 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
-                              s->pic[PXA2XX_PIC_MMC], s->dma);
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC), s->dma);
 
     for (i = 0; pxa255_serial[i].io_base; i ++)
         if (serial_hds[i]) {
 #ifdef TARGET_WORDS_BIGENDIAN
             serial_mm_init(pxa255_serial[i].io_base, 2,
-                           s->pic[pxa255_serial[i].irqn], 14745600/16,
-                           serial_hds[i], 1, 1);
+                            qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
+                            14745600 / 16, serial_hds[i], 1, 1);
 #else
             serial_mm_init(pxa255_serial[i].io_base, 2,
-                           s->pic[pxa255_serial[i].irqn], 14745600/16,
-                           serial_hds[i], 1, 0);
+                            qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
+                            14745600 / 16, serial_hds[i], 1, 0);
 #endif
         } else {
             break;
         }
     if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
+        s->fir = pxa2xx_fir_init(0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
                         s->dma, serial_hds[i]);
 
-    s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD]);
+    s->lcd = pxa2xx_lcdc_init(0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
 
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
@@ -2282,13 +2293,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     for (i = 0; pxa255_ssp[i].io_base; i ++) {
         DeviceState *dev;
         dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
-                                   s->pic[pxa255_ssp[i].irqn]);
+                        qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
         s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
     }
 
     if (usb_enabled) {
         sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                             s->pic[PXA2XX_PIC_USBH1]);
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
     }
 
     s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
@@ -2302,10 +2313,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
                     pxa2xx_rtc_load, s);
 
-    s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 0xffff);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0xff);
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2C), 0xffff);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
-    s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
+    s->i2s = pxa2xx_i2s_init(0x40400000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S), s->dma);
 
     /* GPIO1 resets the processor */
     /* The handler can be overridden by board-specific code */
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 789965d..200b0cf 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -253,7 +253,7 @@ static CPUWriteMemoryFunc * const pxa2xx_gpio_writefn[] = {
 };
 
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, qemu_irq *pic, int lines)
+                CPUState *env, DeviceState *pic, int lines)
 {
     DeviceState *dev;
 
@@ -263,9 +263,12 @@ DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
     qdev_init_nofail(dev);
 
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[PXA2XX_PIC_GPIO_0]);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[PXA2XX_PIC_GPIO_1]);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[PXA2XX_PIC_GPIO_X]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
 
     return dev;
 }
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index a36da23..308d052 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -10,6 +10,7 @@
 
 #include "hw.h"
 #include "pxa.h"
+#include "sysbus.h"
 
 #define ICIP	0x00	/* Interrupt Controller IRQ Pending register */
 #define ICMR	0x04	/* Interrupt Controller Mask register */
@@ -31,6 +32,7 @@
 #define PXA2XX_PIC_SRCS	40
 
 typedef struct {
+    SysBusDevice busdev;
     CPUState *cpu_env;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
@@ -241,51 +243,17 @@ static CPUWriteMemoryFunc * const pxa2xx_pic_writefn[] = {
     pxa2xx_pic_mem_write,
 };
 
-static void pxa2xx_pic_save(QEMUFile *f, void *opaque)
+static int pxa2xx_pic_post_load(void *opaque, int version_id)
 {
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int i;
-
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->int_enabled[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->int_pending[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_put_be32s(f, &s->is_fiq[i]);
-    qemu_put_be32s(f, &s->int_idle);
-    for (i = 0; i < PXA2XX_PIC_SRCS; i ++)
-        qemu_put_be32s(f, &s->priority[i]);
-}
-
-static int pxa2xx_pic_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int i;
-
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->int_enabled[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->int_pending[i]);
-    for (i = 0; i < 2; i ++)
-        qemu_get_be32s(f, &s->is_fiq[i]);
-    qemu_get_be32s(f, &s->int_idle);
-    for (i = 0; i < PXA2XX_PIC_SRCS; i ++)
-        qemu_get_be32s(f, &s->priority[i]);
-
     pxa2xx_pic_update(opaque);
     return 0;
 }
 
-qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
+DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 {
-    PXA2xxPICState *s;
+    DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
     int iomemtype;
-    qemu_irq *qi;
-
-    s = (PXA2xxPICState *)
-            qemu_mallocz(sizeof(PXA2xxPICState));
-    if (!s)
-        return NULL;
+    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
 
     s->cpu_env = env;
 
@@ -296,18 +264,52 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
     s->is_fiq[0] = 0;
     s->is_fiq[1] = 0;
 
-    qi = qemu_allocate_irqs(pxa2xx_pic_set_irq, s, PXA2XX_PIC_SRCS);
+    qdev_init_nofail(dev);
+
+    qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
 
     /* Enable IC memory-mapped registers access.  */
     iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
                     pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00100000, iomemtype);
+    sysbus_init_mmio(sysbus_from_qdev(dev), 0x00100000, iomemtype);
 
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
-    register_savevm(NULL, "pxa2xx_pic", 0, 0, pxa2xx_pic_save,
-                    pxa2xx_pic_load, s);
+    return dev;
+}
+
+static VMStateDescription vmstate_pxa2xx_pic_regs = {
+    .name = "pxa2xx_pic",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = pxa2xx_pic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2),
+        VMSTATE_UINT32_ARRAY(int_pending, PXA2xxPICState, 2),
+        VMSTATE_UINT32_ARRAY(is_fiq, PXA2xxPICState, 2),
+        VMSTATE_UINT32(int_idle, PXA2xxPICState),
+        VMSTATE_UINT32_ARRAY(priority, PXA2xxPICState, PXA2XX_PIC_SRCS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
 
-    return qi;
+static int pxa2xx_pic_initfn(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static SysBusDeviceInfo pxa2xx_pic_info = {
+    .init       = pxa2xx_pic_initfn,
+    .qdev.name  = "pxa2xx_pic",
+    .qdev.desc  = "PXA2xx PIC",
+    .qdev.size  = sizeof(PXA2xxPICState),
+    .qdev.vmsd  = &vmstate_pxa2xx_pic_regs,
+};
+
+static void pxa2xx_pic_register(void)
+{
+    sysbus_register_withprop(&pxa2xx_pic_info);
 }
+device_init(pxa2xx_pic_register);
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index b556d11..7ab2cc3 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -10,6 +10,7 @@
 #include "hw.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
+#include "qdev.h"
 #include "pxa.h"
 
 #define OSMR0	0x00
@@ -428,7 +429,7 @@ static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs)
+                DeviceState *pic)
 {
     int i;
     int iomemtype;
@@ -443,7 +444,7 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
 
     for (i = 0; i < 4; i ++) {
         s->timer[i].value = 0;
-        s->timer[i].irq = irqs[i];
+        s->timer[i].irq = qdev_get_gpio_in(pic, PXA2XX_PIC_OST_0 + i);
         s->timer[i].info = s;
         s->timer[i].num = i;
         s->timer[i].level = 0;
@@ -461,24 +462,23 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
     return s;
 }
 
-void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
+void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
     s->freq = PXA25X_FREQ;
     s->tm4 = NULL;
 }
 
-void pxa27x_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, qemu_irq irq4)
+void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
     int i;
     s->freq = PXA27X_FREQ;
     s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 *
                     sizeof(PXA2xxTimer4));
     for (i = 0; i < 8; i ++) {
         s->tm4[i].tm.value = 0;
-        s->tm4[i].tm.irq = irq4;
+        s->tm4[i].tm.irq = qdev_get_gpio_in(pic, PXA27X_PIC_OST_4_11);
         s->tm4[i].tm.info = s;
         s->tm4[i].tm.num = i + 4;
         s->tm4[i].tm.level = 0;
commit 3e1dbc3bd40338f19a2469feabd5f1dc5a4f5a9d
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Wed Feb 16 16:22:33 2011 +0300

    mst_fpga: correct irq level settings
    
    Final corrections for IRQ levels that are set by mst_fpga:
    
    * Don't retranslate IRQ if previously IRQ was masked.
    * After setting or clearing IRQs through register, apply mask
      before setting parent IRQ level.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index afed2ac..407bac9 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -50,7 +50,7 @@ static void
 mst_fpga_set_irq(void *opaque, int irq, int level)
 {
 	mst_irq_state *s = (mst_irq_state *)opaque;
-	uint32_t oldint = s->intsetclr;
+	uint32_t oldint = s->intsetclr & s->intmskena;
 
 	if (level)
 		s->prev_level |= 1u << irq;
@@ -139,7 +139,7 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 		break;
 	case MST_INTSETCLR:	/* clear or set interrupt */
 		s->intsetclr = (value & 0xFEEFF);
-		qemu_set_irq(s->parent, s->intsetclr);
+		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
 		break;
 	case MST_PCMCIA0:
 		s->pcmcia0 = value;
commit cf76a1ce8b7cf4b92429d67d3f4626a92b2d8a37
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 24 16:04:22 2011 +0000

    ui/vnc-enc-tight.c: Fix compile failure if CONFIG_VNC_JPEG not defined
    
    Add some missing #ifdefs to fix compilation failures in the !CONFIG_VNC_JPEG
    case introduced by commit ce702e93.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 5933394..2522936 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -1536,8 +1536,10 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     uint32_t bg = 0, fg = 0;
     int colors;
     int ret = 0;
+#ifdef CONFIG_VNC_JPEG
     bool force_jpeg = false;
     bool allow_jpeg = true;
+#endif
 
     vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type);
 
@@ -1711,6 +1713,7 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y,
         vs->tight.pixel24 = false;
     }
 
+#ifdef CONFIG_VNC_JPEG
     if (vs->tight.quality != (uint8_t)-1) {
         double freq = vnc_update_freq(vs, x, y, w, h);
 
@@ -1718,6 +1721,7 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y,
             return send_rect_simple(vs, x, y, w, h, false);
         }
     }
+#endif
 
     if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) {
         return send_rect_simple(vs, x, y, w, h, true);
commit a43f9c90c9129d1f28e473277abf793d0caed897
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 24 11:14:12 2011 +0530

    virtio-serial: kill VirtIOSerialDevice
    
    VirtIOSerialDevice is like VirtIOSerialPort with just the first two
    fields, which makes it pretty pointless.  Using VirtIOSerialPort
    directly works equally well and is less confusing.
    
    [Amit: - rebase
           - rename 'dev' to 'port' in function params in virtio-serial.h ]
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 62624ec..c235b27 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -57,10 +57,8 @@ static void chr_event(void *opaque, int event)
     }
 }
 
-static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
+static int generic_port_init(VirtConsole *vcon, VirtIOSerialPort *port)
 {
-    vcon->port.info = dev->info;
-
     if (vcon->chr) {
         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
                               vcon);
@@ -70,18 +68,16 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
 }
 
 /* Virtio Console Ports */
-static int virtconsole_initfn(VirtIOSerialDevice *dev)
+static int virtconsole_initfn(VirtIOSerialPort *port)
 {
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     port->is_console = true;
-    return generic_port_init(vcon, dev);
+    return generic_port_init(vcon, port);
 }
 
-static int virtconsole_exitfn(VirtIOSerialDevice *dev)
+static int virtconsole_exitfn(VirtIOSerialPort *port)
 {
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     if (vcon->chr) {
@@ -113,12 +109,11 @@ static void virtconsole_register(void)
 device_init(virtconsole_register)
 
 /* Generic Virtio Serial Ports */
-static int virtserialport_initfn(VirtIOSerialDevice *dev)
+static int virtserialport_initfn(VirtIOSerialPort *port)
 {
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
-    return generic_port_init(vcon, dev);
+    return generic_port_init(vcon, port);
 }
 
 static VirtIOSerialPortInfo virtserialport_info = {
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index e05ab5e..8446bc2 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -658,8 +658,7 @@ static VirtIOSerialBus *virtser_bus_new(DeviceState *dev)
 
 static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
 {
-    VirtIOSerialDevice *dev = DO_UPCAST(VirtIOSerialDevice, qdev, qdev);
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
+    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
 
     monitor_printf(mon, "%*s dev-prop-int: id: %u\n",
                    indent, "", port->id);
@@ -721,9 +720,8 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
 
 static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
-    VirtIOSerialDevice *dev = DO_UPCAST(VirtIOSerialDevice, qdev, qdev);
+    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
     VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev, base);
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
     VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
     int ret;
     bool plugging_port0;
@@ -761,8 +759,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
         return -1;
     }
 
-    dev->info = info;
-    ret = info->init(dev);
+    port->info = info;
+    ret = info->init(port);
     if (ret) {
         return ret;
     }
@@ -791,8 +789,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
 
 static int virtser_port_qdev_exit(DeviceState *qdev)
 {
-    VirtIOSerialDevice *dev = DO_UPCAST(VirtIOSerialDevice, qdev, qdev);
-    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
+    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
     VirtIOSerial *vser = port->vser;
 
     remove_port(port->vser, port->id);
@@ -800,7 +797,7 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
     QTAILQ_REMOVE(&vser->ports, port, next);
 
     if (port->info->exit)
-        port->info->exit(dev);
+        port->info->exit(port);
 
     return 0;
 }
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index a308196..8cb9fbe 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -62,11 +62,6 @@ typedef struct VirtIOSerialBus VirtIOSerialBus;
 typedef struct VirtIOSerialPort VirtIOSerialPort;
 typedef struct VirtIOSerialPortInfo VirtIOSerialPortInfo;
 
-typedef struct VirtIOSerialDevice {
-    DeviceState qdev;
-    VirtIOSerialPortInfo *info;
-} VirtIOSerialDevice;
-
 /*
  * This is the state that's shared between all the ports.  Some of the
  * state is configurable via command-line options. Some of it can be
@@ -136,12 +131,12 @@ struct VirtIOSerialPortInfo {
      * The per-port (or per-app) init function that's called when a
      * new device is found on the bus.
      */
-    int (*init)(VirtIOSerialDevice *dev);
+    int (*init)(VirtIOSerialPort *port);
     /*
      * Per-port exit function that's called when a port gets
      * hot-unplugged or removed.
      */
-    int (*exit)(VirtIOSerialDevice *dev);
+    int (*exit)(VirtIOSerialPort *port);
 
     /* Callbacks for guest events */
         /* Guest opened device. */
commit 61a11c98b77bb27dda7b2fb7004371bf0437ae5d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Feb 24 16:34:59 2011 +1100

    Add TAGS and *~ to .gitignore
    
    Add the etags output generated by "make TAGS" and editor backup files
    to .gitignore.
    
    This patch has previously appeared in my series of patches to add
    pSeries emulation support.  However, it obviously has no real
    connection to that, and can be applied seperately.
    
    Please apply.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/.gitignore b/.gitignore
index 26703e1..1d79680 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,3 +63,5 @@ pc-bios/optionrom/multiboot.raw
 .stgit-*
 cscope.*
 tags
+TAGS
+*~
commit e07be5d2aeecc64b3d245cd20b9ccbeeedc9d1dd
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Mon Feb 21 17:38:48 2011 +0100

    target-arm: fix support for VRSQRTE.
    
    Now use the same algorithm as described in the ARM ARM.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 031f2ec..1852352 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2755,11 +2755,104 @@ float32 HELPER(recpe_f32)(float32 a, CPUState *env)
     return make_float32(val32);
 }
 
+/* The algorithm that must be used to calculate the estimate
+ * is specified by the ARM ARM.
+ */
+static float64 recip_sqrt_estimate(float64 a, CPUState *env)
+{
+    float_status *s = &env->vfp.standard_fp_status;
+    float64 q;
+    int64_t q_int;
+
+    if (float64_lt(a, float64_half, s)) {
+        /* range 0.25 <= a < 0.5 */
+
+        /* a in units of 1/512 rounded down */
+        /* q0 = (int)(a * 512.0);  */
+        q = float64_mul(float64_512, a, s);
+        q_int = float64_to_int64_round_to_zero(q, s);
+
+        /* reciprocal root r */
+        /* r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);  */
+        q = int64_to_float64(q_int, s);
+        q = float64_add(q, float64_half, s);
+        q = float64_div(q, float64_512, s);
+        q = float64_sqrt(q, s);
+        q = float64_div(float64_one, q, s);
+    } else {
+        /* range 0.5 <= a < 1.0 */
+
+        /* a in units of 1/256 rounded down */
+        /* q1 = (int)(a * 256.0); */
+        q = float64_mul(float64_256, a, s);
+        int64_t q_int = float64_to_int64_round_to_zero(q, s);
+
+        /* reciprocal root r */
+        /* r = 1.0 /sqrt(((double)q1 + 0.5) / 256); */
+        q = int64_to_float64(q_int, s);
+        q = float64_add(q, float64_half, s);
+        q = float64_div(q, float64_256, s);
+        q = float64_sqrt(q, s);
+        q = float64_div(float64_one, q, s);
+    }
+    /* r in units of 1/256 rounded to nearest */
+    /* s = (int)(256.0 * r + 0.5); */
+
+    q = float64_mul(q, float64_256,s );
+    q = float64_add(q, float64_half, s);
+    q_int = float64_to_int64_round_to_zero(q, s);
+
+    /* return (double)s / 256.0;*/
+    return float64_div(int64_to_float64(q_int, s), float64_256, s);
+}
+
 float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
 {
-    float_status *s = &env->vfp.fp_status;
-    float32 one = int32_to_float32(1, s);
-    return float32_div(one, float32_sqrt(a, s), s);
+    float_status *s = &env->vfp.standard_fp_status;
+    int result_exp;
+    float64 f64;
+    uint32_t val;
+    uint64_t val64;
+
+    val = float32_val(a);
+
+    if (float32_is_any_nan(a)) {
+        if (float32_is_signaling_nan(a)) {
+            float_raise(float_flag_invalid, s);
+        }
+        return float32_default_nan;
+    } else if (float32_is_zero_or_denormal(a)) {
+        float_raise(float_flag_divbyzero, s);
+        return float32_set_sign(float32_infinity, float32_is_neg(a));
+    } else if (float32_is_neg(a)) {
+        float_raise(float_flag_invalid, s);
+        return float32_default_nan;
+    } else if (float32_is_infinity(a)) {
+        return float32_zero;
+    }
+
+    /* Normalize to a double-precision value between 0.25 and 1.0,
+     * preserving the parity of the exponent.  */
+    if ((val & 0x800000) == 0) {
+        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
+                           | (0x3feULL << 52)
+                           | ((uint64_t)(val & 0x7fffff) << 29));
+    } else {
+        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
+                           | (0x3fdULL << 52)
+                           | ((uint64_t)(val & 0x7fffff) << 29));
+    }
+
+    result_exp = (380 - ((val & 0x7f800000) >> 23)) / 2;
+
+    f64 = recip_sqrt_estimate(f64, env);
+
+    val64 = float64_val(f64);
+
+    val = ((val64 >> 63)  & 0x80000000)
+        | ((result_exp & 0xff) << 23)
+        | ((val64 >> 29)  & 0x7fffff);
+    return make_float32(val);
 }
 
 uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
@@ -2780,13 +2873,23 @@ uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
 
 uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
 {
-    float_status *s = &env->vfp.fp_status;
-    float32 tmp;
-    tmp = int32_to_float32(a, s);
-    tmp = float32_scalbn(tmp, -32, s);
-    tmp = helper_rsqrte_f32(tmp, env);
-    tmp = float32_scalbn(tmp, 31, s);
-    return float32_to_int32(tmp, s);
+    float64 f64;
+
+    if ((a & 0xc0000000) == 0) {
+        return 0xffffffff;
+    }
+
+    if (a & 0x80000000) {
+        f64 = make_float64((0x3feULL << 52)
+                           | ((uint64_t)(a & 0x7fffffff) << 21));
+    } else { /* bits 31-30 == '01' */
+        f64 = make_float64((0x3fdULL << 52)
+                           | ((uint64_t)(a & 0x3fffffff) << 22));
+    }
+
+    f64 = recip_sqrt_estimate(f64, env);
+
+    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
 }
 
 void HELPER(set_teecr)(CPUState *env, uint32_t val)
commit fe0e4872e46a5264ea433a22a793538545108564
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Mon Feb 21 17:38:47 2011 +0100

    target-arm: fix support for VRECPE.
    
    Now use the same algorithm as described in the ARM ARM.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 30c1809..031f2ec 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2692,13 +2692,67 @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
 #define float64_256 make_float64(0x4070000000000000LL)
 #define float64_512 make_float64(0x4080000000000000LL)
 
-/* TODO: The architecture specifies the value that the estimate functions
-   should return.  We return the exact reciprocal/root instead.  */
+/* The algorithm that must be used to calculate the estimate
+ * is specified by the ARM ARM.
+ */
+static float64 recip_estimate(float64 a, CPUState *env)
+{
+    float_status *s = &env->vfp.standard_fp_status;
+    /* q = (int)(a * 512.0) */
+    float64 q = float64_mul(float64_512, a, s);
+    int64_t q_int = float64_to_int64_round_to_zero(q, s);
+
+    /* r = 1.0 / (((double)q + 0.5) / 512.0) */
+    q = int64_to_float64(q_int, s);
+    q = float64_add(q, float64_half, s);
+    q = float64_div(q, float64_512, s);
+    q = float64_div(float64_one, q, s);
+
+    /* s = (int)(256.0 * r + 0.5) */
+    q = float64_mul(q, float64_256, s);
+    q = float64_add(q, float64_half, s);
+    q_int = float64_to_int64_round_to_zero(q, s);
+
+    /* return (double)s / 256.0 */
+    return float64_div(int64_to_float64(q_int, s), float64_256, s);
+}
+
 float32 HELPER(recpe_f32)(float32 a, CPUState *env)
 {
-    float_status *s = &env->vfp.fp_status;
-    float32 one = int32_to_float32(1, s);
-    return float32_div(one, a, s);
+    float_status *s = &env->vfp.standard_fp_status;
+    float64 f64;
+    uint32_t val32 = float32_val(a);
+
+    int result_exp;
+    int a_exp = (val32  & 0x7f800000) >> 23;
+    int sign = val32 & 0x80000000;
+
+    if (float32_is_any_nan(a)) {
+        if (float32_is_signaling_nan(a)) {
+            float_raise(float_flag_invalid, s);
+        }
+        return float32_default_nan;
+    } else if (float32_is_infinity(a)) {
+        return float32_set_sign(float32_zero, float32_is_neg(a));
+    } else if (float32_is_zero_or_denormal(a)) {
+        float_raise(float_flag_divbyzero, s);
+        return float32_set_sign(float32_infinity, float32_is_neg(a));
+    } else if (a_exp >= 253) {
+        float_raise(float_flag_underflow, s);
+        return float32_set_sign(float32_zero, float32_is_neg(a));
+    }
+
+    f64 = make_float64((0x3feULL << 52)
+                       | ((int64_t)(val32 & 0x7fffff) << 29));
+
+    result_exp = 253 - a_exp;
+
+    f64 = recip_estimate(f64, env);
+
+    val32 = sign
+        | ((result_exp & 0xff) << 23)
+        | ((float64_val(f64) >> 29) & 0x7fffff);
+    return make_float32(val32);
 }
 
 float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
@@ -2710,13 +2764,18 @@ float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
 
 uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
 {
-    float_status *s = &env->vfp.fp_status;
-    float32 tmp;
-    tmp = int32_to_float32(a, s);
-    tmp = float32_scalbn(tmp, -32, s);
-    tmp = helper_recpe_f32(tmp, env);
-    tmp = float32_scalbn(tmp, 31, s);
-    return float32_to_int32(tmp, s);
+    float64 f64;
+
+    if ((a & 0x80000000) == 0) {
+        return 0xffffffff;
+    }
+
+    f64 = make_float64((0x3feULL << 52)
+                       | ((int64_t)(a & 0x7fffffff) << 21));
+
+    f64 = recip_estimate (f64, env);
+
+    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
 }
 
 uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
commit 56bf4fe2978e3e14c976feae825dbbd3700573d0
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Mon Feb 21 17:38:46 2011 +0100

    target-arm: Introduce float64_256 and float64_512 constants.
    
    These two constants will be used by helper functions such as recpe_f32
    and rsqrte_f32.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7f63a28..30c1809 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2687,6 +2687,11 @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
 
 /* NEON helpers.  */
 
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
+ * int->float conversions at run-time.  */
+#define float64_256 make_float64(0x4070000000000000LL)
+#define float64_512 make_float64(0x4080000000000000LL)
+
 /* TODO: The architecture specifies the value that the estimate functions
    should return.  We return the exact reciprocal/root instead.  */
 float32 HELPER(recpe_f32)(float32 a, CPUState *env)
commit c30fe7dfc44cf6ca0213e0c15f92cf00f796721b
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Mon Feb 21 17:38:45 2011 +0100

    softfloat: add _set_sign(), _infinity and _half for 32 and 64 bits floats.
    
    These constants and utility function are needed to implement some
    helpers. Defining constants avoids the need to re-compute them at
    runtime.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index f34a938..fd61dc4 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -379,9 +379,16 @@ INLINE int float32_is_zero_or_denormal(float32 a)
     return (float32_val(a) & 0x7f800000) == 0;
 }
 
+INLINE float32 float32_set_sign(float32 a, int sign)
+{
+    return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31));
+}
+
 #define float32_zero make_float32(0)
 #define float32_one make_float32(0x3f800000)
 #define float32_ln2 make_float32(0x3f317218)
+#define float32_half make_float32(0x3f000000)
+#define float32_infinity make_float32(0x7f800000)
 
 
 /*----------------------------------------------------------------------------
@@ -479,9 +486,17 @@ INLINE int float64_is_any_nan(float64 a)
     return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
 }
 
+INLINE float64 float64_set_sign(float64 a, int sign)
+{
+    return make_float64((float64_val(a) & 0x7fffffffffffffffULL)
+                        | ((int64_t)sign << 63));
+}
+
 #define float64_zero make_float64(0)
 #define float64_one make_float64(0x3ff0000000000000LL)
 #define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
+#define float64_half make_float64(0x3fe0000000000000LL)
+#define float64_infinity make_float64(0x7ff0000000000000LL)
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
commit 8559666ddb50a721bee06d281d5fa87ef44749ba
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Mon Feb 21 17:38:44 2011 +0100

    softfloat: move all default NaN definitions to softfloat.h.
    
    These special values are needed to implement some helper functions,
    which return/use these values in some cases.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 2d025bf..adc5ada 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -30,12 +30,6 @@ these four paragraphs for those parts of this code that are retained.
 
 =============================================================================*/
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4)
-#define SNAN_BIT_IS_ONE		1
-#else
-#define SNAN_BIT_IS_ONE		0
-#endif
-
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
 | defined here if desired.  It is currently not possible for such a trap
@@ -57,17 +51,6 @@ typedef struct {
 } commonNaNT;
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated half-precision NaN.
-*----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-#define float16_default_nan make_float16(0x7E00)
-#elif SNAN_BIT_IS_ONE
-#define float16_default_nan make_float16(0x7DFF)
-#else
-#define float16_default_nan make_float16(0xFE00)
-#endif
-
-/*----------------------------------------------------------------------------
 | Returns 1 if the half-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
@@ -158,19 +141,6 @@ static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
 }
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated single-precision NaN.
-*----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float32_default_nan make_float32(0x7FFFFFFF)
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float32_default_nan make_float32(0x7FC00000)
-#elif SNAN_BIT_IS_ONE
-#define float32_default_nan make_float32(0x7FBFFFFF)
-#else
-#define float32_default_nan make_float32(0xFFC00000)
-#endif
-
-/*----------------------------------------------------------------------------
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
@@ -413,19 +383,6 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 }
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated double-precision NaN.
-*----------------------------------------------------------------------------*/
-#if defined(TARGET_SPARC)
-#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
-#elif SNAN_BIT_IS_ONE
-#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
-#else
-#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
-#endif
-
-/*----------------------------------------------------------------------------
 | Returns 1 if the double-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
@@ -564,19 +521,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.  The
-| `high' and `low' values hold the most- and least-significant bits,
-| respectively.
-*----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define floatx80_default_nan_high 0x7FFF
-#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
-#else
-#define floatx80_default_nan_high 0xFFFF
-#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
-#endif
-
-/*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is a
 | quiet NaN; otherwise returns 0. This slightly differs from the same
 | function for other types as floatx80 has an explicit bit.
@@ -728,18 +672,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
 #ifdef FLOAT128
 
 /*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.  The `high' and
-| `low' values hold the most- and least-significant bits, respectively.
-*----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
-#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
-#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
-#else
-#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
-#define float128_default_nan_low  LIT64( 0x0000000000000000 )
-#endif
-
-/*----------------------------------------------------------------------------
 | Returns 1 if the quadruple-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index e57ee1e..f34a938 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -77,6 +77,12 @@ typedef int64_t sbits64;
 #define LIT64( a ) a##LL
 #define INLINE static inline
 
+#if defined(TARGET_MIPS) || defined(TARGET_SH4)
+#define SNAN_BIT_IS_ONE		1
+#else
+#define SNAN_BIT_IS_ONE		0
+#endif
+
 /*----------------------------------------------------------------------------
 | The macro `FLOATX80' must be defined to enable the extended double-precision
 | floating-point format `floatx80'.  If this macro is not defined, the
@@ -278,6 +284,17 @@ int float16_is_signaling_nan( float16 );
 float16 float16_maybe_silence_nan( float16 );
 
 /*----------------------------------------------------------------------------
+| The pattern for a default generated half-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_ARM)
+#define float16_default_nan make_float16(0x7E00)
+#elif SNAN_BIT_IS_ONE
+#define float16_default_nan make_float16(0x7DFF)
+#else
+#define float16_default_nan make_float16(0xFE00)
+#endif
+
+/*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int float32_to_int16_round_to_zero( float32 STATUS_PARAM );
@@ -366,6 +383,20 @@ INLINE int float32_is_zero_or_denormal(float32 a)
 #define float32_one make_float32(0x3f800000)
 #define float32_ln2 make_float32(0x3f317218)
 
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated single-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+#define float32_default_nan make_float32(0x7FFFFFFF)
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+#define float32_default_nan make_float32(0x7FC00000)
+#elif SNAN_BIT_IS_ONE
+#define float32_default_nan make_float32(0x7FBFFFFF)
+#else
+#define float32_default_nan make_float32(0xFFC00000)
+#endif
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
@@ -452,6 +483,19 @@ INLINE int float64_is_any_nan(float64 a)
 #define float64_one make_float64(0x3ff0000000000000LL)
 #define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
 
+/*----------------------------------------------------------------------------
+| The pattern for a default generated double-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_SPARC)
+#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
+#elif SNAN_BIT_IS_ONE
+#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
+#else
+#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
+#endif
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -520,6 +564,19 @@ INLINE int floatx80_is_any_nan(floatx80 a)
     return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
 }
 
+/*----------------------------------------------------------------------------
+| The pattern for a default generated extended double-precision NaN.  The
+| `high' and `low' values hold the most- and least-significant bits,
+| respectively.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define floatx80_default_nan_high 0x7FFF
+#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
+#else
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+#endif
+
 #endif
 
 #ifdef FLOAT128
@@ -593,6 +650,18 @@ INLINE int float128_is_any_nan(float128 a)
         ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
 }
 
+/*----------------------------------------------------------------------------
+| The pattern for a default generated quadruple-precision NaN.  The `high' and
+| `low' values hold the most- and least-significant bits, respectively.
+*----------------------------------------------------------------------------*/
+#if SNAN_BIT_IS_ONE
+#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
+#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
+#else
+#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
+#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+#endif
+
 #endif
 
 #else /* CONFIG_SOFTFLOAT */
commit fb1ba03ab064ae2e2e8248df81a7cad805dbe9d8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 18 13:39:00 2011 +0000

    hw/sd.c: Add missing state change for SD_STATUS, SEND_NUM_WR_BLOCKS
    
    The SD_STATUS and SEND_NUM_WR_BLOCKS commands are supposed to cause
    the card to send data back to the host. However sd.c was missing the
    state change to sd_sendingdata_state for these commands, with the effect
    that the Linux driver would either hang indefinitely waiting for
    nonexistent data (pl181) or read zeroes and provoke a qemu warning
    message (omap).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/sd.c b/hw/sd.c
index 789ca84..5e29752 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1168,6 +1168,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
     case 13:	/* ACMD13: SD_STATUS */
         switch (sd->state) {
         case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
             sd->data_start = 0;
             sd->data_offset = 0;
             return sd_r1;
@@ -1182,6 +1183,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
         case sd_transfer_state:
             *(uint32_t *) sd->data = sd->blk_written;
 
+            sd->state = sd_sendingdata_state;
             sd->data_start = 0;
             sd->data_offset = 0;
             return sd_r1;
commit 5db8378a7710df7899544004967597eb395418c2
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Feb 16 20:48:00 2011 +0100

    vnc: Fix fatal crash with vnc reverse mode
    
    Reverse mode is unusable:
    
    	qemu -vnc localhost:5500,reverse
    
    crashes in vnc_refresh_server_surface because some pointers are NULL.
    
    Fix this by calling vnc_dpy_resize (which initializes these pointers)
    before calling vnc_refresh.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 626b430..610f884 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2480,6 +2480,7 @@ static void vnc_init_timer(VncDisplay *vd)
     vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
     if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
         vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
+        vnc_dpy_resize(vd->ds);
         vnc_refresh(vd);
     }
 }
commit 80e0c8c39b663cd44ea8d47efe256897b7102f50
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:08 2011 +0100

    vnc: add a non-adaptive option
    
    This option allow to disable adaptive behaviors in some encodings.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 945edf3..badb730 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -913,6 +913,15 @@ option is set, VNC client may receive lossy framebuffer updates
 depending on its encoding settings. Enabling this option can save
 a lot of bandwidth at the expense of quality.
 
+ at item non-adaptive
+
+Disable adaptive encodings. Adaptive encodings are enabled by default.
+An adaptive encoding will try to detect frequently updated screen regions,
+and send updates in these regions using a lossy encoding (like JPEG).
+This can be really helpfull to save bandwidth when playing videos. Disabling
+adaptive encodings allow to restore the original static behavior of encodings
+like Tight.
+
 @end table
 ETEXI
 
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 82c1e96..5933394 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -1546,7 +1546,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     vnc_tight_stop(vs);
 
 #ifdef CONFIG_VNC_JPEG
-    if (vs->tight.quality != (uint8_t)-1) {
+    if (!vs->vd->non_adaptive && vs->tight.quality != (uint8_t)-1) {
         double freq = vnc_update_freq(vs, x, y, w, h);
 
         if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) {
diff --git a/ui/vnc.c b/ui/vnc.c
index 86c2320..626b430 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2387,10 +2387,12 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     VncState *vs;
     int has_dirty = 0;
 
-    struct timeval tv;
+    struct timeval tv = { 0, 0 };
 
-    gettimeofday(&tv, NULL);
-    has_dirty = vnc_update_stats(vd, &tv);
+    if (!vd->non_adaptive) {
+        gettimeofday(&tv, NULL);
+        has_dirty = vnc_update_stats(vd, &tv);
+    }
 
     /*
      * Walk through the guest dirty map.
@@ -2419,7 +2421,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
                 if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
                     continue;
                 memcpy(server_ptr, guest_ptr, cmp_bytes);
-                vnc_rect_updated(vd, x, y, &tv);
+                if (!vd->non_adaptive)
+                    vnc_rect_updated(vd, x, y, &tv);
                 QTAILQ_FOREACH(vs, &vd->clients, next) {
                     set_bit((x / 16), vs->dirty[y]);
                 }
@@ -2754,6 +2757,8 @@ int vnc_display_open(DisplayState *ds, const char *display)
 #endif
         } else if (strncmp(options, "lossy", 5) == 0) {
             vs->lossy = true;
+        } else if (strncmp(options, "non-adapative", 13) == 0) {
+            vs->non_adaptive = true;
         }
     }
 
diff --git a/ui/vnc.h b/ui/vnc.h
index 98a1885..8a1e7b9 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -144,6 +144,7 @@ struct VncDisplay
     time_t expires;
     int auth;
     bool lossy;
+    bool non_adaptive;
 #ifdef CONFIG_VNC_TLS
     int subauth; /* Used by VeNCrypt */
     VncDisplayTLS tls;
commit 8cb4a6b755788925eea2beead87e201dfd4ba8bc
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:07 2011 +0100

    vnc: tight: tweak adaptive tight settings
    
    The force_jpeg threshold was too low.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 81024d5..82c1e96 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -79,16 +79,16 @@ static const struct {
     int jpeg_idx;               /* Allow indexed JPEG */
     int jpeg_full;              /* Allow full color JPEG */
 } tight_jpeg_conf[] = {
-    { 0,   4,  1, 1 },
-    { 0,   4,  1, 1 },
-    { 0,   4,  1, 1 },
-    { 0,   4,  1, 1 },
-    { 0,   4,  0, 1 },
-    { 0.1, 4,  0, 1 },
-    { 0.2, 4,  0, 1 },
-    { 0.3, 6,  0, 0 },
-    { 0.4, 8,  0, 0 },
-    { 0.5, 10, 0, 0 },
+    { 0,   8,  1, 1 },
+    { 0,   8,  1, 1 },
+    { 0,   8,  1, 1 },
+    { 0,   8,  1, 1 },
+    { 0,   10, 1, 1 },
+    { 0.1, 10, 1, 1 },
+    { 0.2, 10, 1, 1 },
+    { 0.3, 12, 0, 0 },
+    { 0.4, 14, 0, 0 },
+    { 0.5, 16, 0, 0 },
 };
 #endif
 
commit 6c71a539c3cb3927fdea230c3ddb9e273142570f
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:06 2011 +0100

    vnc: don't try to send bigger updates that client height
    
    Respect client size if it doesn't not support desktop resizing.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 6c57b0e..86c2320 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -795,12 +795,11 @@ static void vnc_dpy_cursor_define(QEMUCursor *c)
 }
 
 static int find_and_clear_dirty_height(struct VncState *vs,
-                                       int y, int last_x, int x)
+                                       int y, int last_x, int x, int height)
 {
     int h;
-    VncDisplay *vd = vs->vd;
 
-    for (h = 1; h < (vd->server->height - y); h++) {
+    for (h = 1; h < (height - y); h++) {
         int tmp_x;
         if (!test_bit(last_x, vs->dirty[y + h])) {
             break;
@@ -865,7 +864,8 @@ static int vnc_update_client(VncState *vs, int has_dirty)
                     }
                 } else {
                     if (last_x != -1) {
-                        int h = find_and_clear_dirty_height(vs, y, last_x, x);
+                        int h = find_and_clear_dirty_height(vs, y, last_x, x,
+                                                            height);
 
                         n += vnc_job_add_rect(job, last_x * 16, y,
                                               (x - last_x) * 16, h);
@@ -874,7 +874,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
                 }
             }
             if (last_x != -1) {
-                int h = find_and_clear_dirty_height(vs, y, last_x, x);
+                int h = find_and_clear_dirty_height(vs, y, last_x, x, height);
                 n += vnc_job_add_rect(job, last_x * 16, y,
                                       (x - last_x) * 16, h);
             }
commit bc2429b9174ac2d3c56b7fd35884b0d89ec7fb02
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:05 2011 +0100

    vnc: use the new generic bitmap functions
    
    Switch to bitmap.h and bitops.h instead of redefining our own bitmap
    helpers.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 8c7cb0d..6c57b0e 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -41,13 +41,6 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
 #include "vnc_keysym.h"
 #include "d3des.h"
 
-#define count_bits(c, v) { \
-    for (c = 0; v; v >>= 1) \
-    { \
-        c += v & 1; \
-    } \
-}
-
 static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
 
@@ -378,47 +371,6 @@ static void framebuffer_update_request(VncState *vs, int incremental,
 static void vnc_refresh(void *opaque);
 static int vnc_refresh_server_surface(VncDisplay *vd);
 
-static inline void vnc_set_bit(uint32_t *d, int k)
-{
-    d[k >> 5] |= 1 << (k & 0x1f);
-}
-
-static inline void vnc_clear_bit(uint32_t *d, int k)
-{
-    d[k >> 5] &= ~(1 << (k & 0x1f));
-}
-
-static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
-{
-    int j;
-
-    j = 0;
-    while (n >= 32) {
-        d[j++] = -1;
-        n -= 32;
-    }
-    if (n > 0)
-        d[j++] = (1 << n) - 1;
-    while (j < nb_words)
-        d[j++] = 0;
-}
-
-static inline int vnc_get_bit(const uint32_t *d, int k)
-{
-    return (d[k >> 5] >> (k & 0x1f)) & 1;
-}
-
-static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
-                               int nb_words)
-{
-    int i;
-    for(i = 0; i < nb_words; i++) {
-        if ((d1[i] & d2[i]) != 0)
-            return 1;
-    }
-    return 0;
-}
-
 static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
 {
     int i;
@@ -441,7 +393,7 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
 
     for (; y < h; y++)
         for (i = 0; i < w; i += 16)
-            vnc_set_bit(s->dirty[y], (x + i) / 16);
+            set_bit((x + i) / 16, s->dirty[y]);
 }
 
 void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
@@ -780,7 +732,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
             memmove(dst_row, src_row, cmp_bytes);
             QTAILQ_FOREACH(vs, &vd->clients, next) {
                 if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
-                    vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16));
+                    set_bit(((x + dst_x) / 16), vs->dirty[y]);
                 }
             }
         }
@@ -850,10 +802,12 @@ static int find_and_clear_dirty_height(struct VncState *vs,
 
     for (h = 1; h < (vd->server->height - y); h++) {
         int tmp_x;
-        if (!vnc_get_bit(vs->dirty[y + h], last_x))
+        if (!test_bit(last_x, vs->dirty[y + h])) {
             break;
-        for (tmp_x = last_x; tmp_x < x; tmp_x++)
-            vnc_clear_bit(vs->dirty[y + h], tmp_x);
+        }
+        for (tmp_x = last_x; tmp_x < x; tmp_x++) {
+            clear_bit(tmp_x, vs->dirty[y + h]);
+        }
     }
 
     return h;
@@ -905,11 +859,10 @@ static int vnc_update_client(VncState *vs, int has_dirty)
             int x;
             int last_x = -1;
             for (x = 0; x < width / 16; x++) {
-                if (vnc_get_bit(vs->dirty[y], x)) {
+                if (test_and_clear_bit(x, vs->dirty[y])) {
                     if (last_x == -1) {
                         last_x = x;
                     }
-                    vnc_clear_bit(vs->dirty[y], x);
                 } else {
                     if (last_x != -1) {
                         int h = find_and_clear_dirty_height(vs, y, last_x, x);
@@ -1702,8 +1655,7 @@ static void framebuffer_update_request(VncState *vs, int incremental,
     if (!incremental) {
         vs->force_update = 1;
         for (i = 0; i < h; i++) {
-            vnc_set_bits(vs->dirty[y_position + i],
-                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
+            bitmap_set(vs->dirty[y_position + i], x_position / 16, w / 16);
         }
     }
 }
@@ -1842,15 +1794,15 @@ static void set_pixel_format(VncState *vs,
 
     vs->clientds = *(vs->vd->guest.ds);
     vs->clientds.pf.rmax = red_max;
-    count_bits(vs->clientds.pf.rbits, red_max);
+    vs->clientds.pf.rbits = hweight_long(red_max);
     vs->clientds.pf.rshift = red_shift;
     vs->clientds.pf.rmask = red_max << red_shift;
     vs->clientds.pf.gmax = green_max;
-    count_bits(vs->clientds.pf.gbits, green_max);
+    vs->clientds.pf.gbits = hweight_long(green_max);
     vs->clientds.pf.gshift = green_shift;
     vs->clientds.pf.gmask = green_max << green_shift;
     vs->clientds.pf.bmax = blue_max;
-    count_bits(vs->clientds.pf.bbits, blue_max);
+    vs->clientds.pf.bbits = hweight_long(blue_max);
     vs->clientds.pf.bshift = blue_shift;
     vs->clientds.pf.bmask = blue_max << blue_shift;
     vs->clientds.pf.bits_per_pixel = bits_per_pixel;
@@ -2315,7 +2267,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
     x = x / VNC_STAT_RECT * VNC_STAT_RECT;
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
-        int j, i;
+        int j;
 
         /* kernel send buffers are full -> refresh later */
         if (vs->output.offset) {
@@ -2328,9 +2280,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
 
         vs->lossy_rect[sty][stx] = 0;
         for (j = 0; j < VNC_STAT_RECT; ++j) {
-            for (i = x / 16; i < VNC_STAT_RECT / 16 + x / 16; ++i) {
-                vnc_set_bit(vs->dirty[y + j], i);
-            }
+            bitmap_set(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
         }
         has_dirty++;
     }
@@ -2433,7 +2383,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     uint8_t *guest_row;
     uint8_t *server_row;
     int cmp_bytes;
-    uint32_t width_mask[VNC_DIRTY_WORDS];
+    unsigned long width_mask[VNC_DIRTY_WORDS];
     VncState *vs;
     int has_dirty = 0;
 
@@ -2447,12 +2397,14 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
      * Check and copy modified bits from guest to server surface.
      * Update server dirty map.
      */
-    vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
+    bitmap_set(width_mask, 0, (ds_get_width(vd->ds) / 16));
+    bitmap_clear(width_mask, (ds_get_width(vd->ds) / 16),
+                 VNC_DIRTY_WORDS * BITS_PER_LONG);
     cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
     guest_row  = vd->guest.ds->data;
     server_row = vd->server->data;
     for (y = 0; y < vd->guest.ds->height; y++) {
-        if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
+        if (bitmap_intersects(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
             int x;
             uint8_t *guest_ptr;
             uint8_t *server_ptr;
@@ -2462,15 +2414,14 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
 
             for (x = 0; x < vd->guest.ds->width;
                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
-                if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
+                if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
                     continue;
-                vnc_clear_bit(vd->guest.dirty[y], (x / 16));
                 if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
                     continue;
                 memcpy(server_ptr, guest_ptr, cmp_bytes);
                 vnc_rect_updated(vd, x, y, &tv);
                 QTAILQ_FOREACH(vs, &vd->clients, next) {
-                    vnc_set_bit(vs->dirty[y], (x / 16));
+                    set_bit((x / 16), vs->dirty[y]);
                 }
                 has_dirty++;
             }
diff --git a/ui/vnc.h b/ui/vnc.h
index 706ba3c..98a1885 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -35,6 +35,7 @@
 #include "console.h"
 #include "monitor.h"
 #include "audio/audio.h"
+#include "bitmap.h"
 #include <zlib.h>
 #include <stdbool.h>
 
@@ -80,7 +81,7 @@ typedef void VncSendHextileTile(VncState *vs,
 
 #define VNC_MAX_WIDTH 2560
 #define VNC_MAX_HEIGHT 2048
-#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
+#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * BITS_PER_LONG))
 
 #define VNC_STAT_RECT  64
 #define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT)
@@ -113,7 +114,7 @@ typedef struct VncRectStat VncRectStat;
 struct VncSurface
 {
     struct timeval last_freq_check;
-    uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    unsigned long dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
     VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
     DisplaySurface *ds;
 };
@@ -232,7 +233,7 @@ struct VncState
     int csock;
 
     DisplayState *ds;
-    uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    unsigned long dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
     uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in
                            * vnc-jobs-async.c */
 
commit e0e53b2f1b7aaf341ddb629ce861e02b2ac95fad
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:04 2011 +0100

    bitmap: add a generic bitmap and bitops library
    
    Add most used bitmap and bitops functions into bitmap.c and bitops.c.
    Theses functions are mostly copied from Linux kernel source.
    
    Some of these functions are already redefined in the VNC server. Some
    of them could be used for some block stuff. The yet yo be submitted
    NUMA work also need bitmaps.
    
    bitops_ffsl() and bitops_flsl() are here because bitops/bitmap works
    on unsigned long, not int, and we can't use current code because:
    * ffs only works on int
    * qemu_fls only works on int
    * ffsl is a GNU extension
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 2ac995b..9e98a66 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -100,6 +100,7 @@ common-obj-y += msmouse.o ps2.o
 common-obj-y += qdev.o qdev-properties.o
 common-obj-y += block-migration.o
 common-obj-y += pflib.o
+common-obj-y += bitmap.o bitops.o
 
 common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
diff --git a/bitmap.c b/bitmap.c
new file mode 100644
index 0000000..a62c8ba
--- /dev/null
+++ b/bitmap.c
@@ -0,0 +1,256 @@
+/*
+ * Bitmap Module
+ *
+ * Stolen from linux/src/lib/bitmap.c
+ *
+ * Copyright (C) 2010 Corentin Chary
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.
+ */
+
+#include "bitops.h"
+#include "bitmap.h"
+
+/*
+ * bitmaps provide an array of bits, implemented using an an
+ * array of unsigned longs.  The number of valid bits in a
+ * given bitmap does _not_ need to be an exact multiple of
+ * BITS_PER_LONG.
+ *
+ * The possible unused bits in the last, partially used word
+ * of a bitmap are 'don't care'.  The implementation makes
+ * no particular effort to keep them zero.  It ensures that
+ * their value will not affect the results of any operation.
+ * The bitmap operations that return Boolean (bitmap_empty,
+ * for example) or scalar (bitmap_weight, for example) results
+ * carefully filter out these unused bits from impacting their
+ * results.
+ *
+ * These operations actually hold to a slightly stronger rule:
+ * if you don't input any bitmaps to these ops that have some
+ * unused bits set, then they won't output any set unused bits
+ * in output bitmaps.
+ *
+ * The byte ordering of bitmaps is more natural on little
+ * endian architectures.
+ */
+
+int slow_bitmap_empty(const unsigned long *bitmap, int bits)
+{
+    int k, lim = bits/BITS_PER_LONG;
+
+    for (k = 0; k < lim; ++k) {
+        if (bitmap[k]) {
+            return 0;
+        }
+    }
+    if (bits % BITS_PER_LONG) {
+        if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int slow_bitmap_full(const unsigned long *bitmap, int bits)
+{
+    int k, lim = bits/BITS_PER_LONG;
+
+    for (k = 0; k < lim; ++k) {
+        if (~bitmap[k]) {
+            return 0;
+        }
+    }
+
+    if (bits % BITS_PER_LONG) {
+        if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int slow_bitmap_equal(const unsigned long *bitmap1,
+                      const unsigned long *bitmap2, int bits)
+{
+    int k, lim = bits/BITS_PER_LONG;
+
+    for (k = 0; k < lim; ++k) {
+        if (bitmap1[k] != bitmap2[k]) {
+            return 0;
+        }
+    }
+
+    if (bits % BITS_PER_LONG) {
+        if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
+                            int bits)
+{
+    int k, lim = bits/BITS_PER_LONG;
+
+    for (k = 0; k < lim; ++k) {
+        dst[k] = ~src[k];
+    }
+
+    if (bits % BITS_PER_LONG) {
+        dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
+    }
+}
+
+int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+                    const unsigned long *bitmap2, int bits)
+{
+    int k;
+    int nr = BITS_TO_LONGS(bits);
+    unsigned long result = 0;
+
+    for (k = 0; k < nr; k++) {
+        result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+    }
+    return result != 0;
+}
+
+void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+                    const unsigned long *bitmap2, int bits)
+{
+    int k;
+    int nr = BITS_TO_LONGS(bits);
+
+    for (k = 0; k < nr; k++) {
+        dst[k] = bitmap1[k] | bitmap2[k];
+    }
+}
+
+void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+                     const unsigned long *bitmap2, int bits)
+{
+    int k;
+    int nr = BITS_TO_LONGS(bits);
+
+    for (k = 0; k < nr; k++) {
+        dst[k] = bitmap1[k] ^ bitmap2[k];
+    }
+}
+
+int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+                       const unsigned long *bitmap2, int bits)
+{
+    int k;
+    int nr = BITS_TO_LONGS(bits);
+    unsigned long result = 0;
+
+    for (k = 0; k < nr; k++) {
+        result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+    }
+    return result != 0;
+}
+
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
+
+void bitmap_set(unsigned long *map, int start, int nr)
+{
+    unsigned long *p = map + BIT_WORD(start);
+    const int size = start + nr;
+    int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+    unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+    while (nr - bits_to_set >= 0) {
+        *p |= mask_to_set;
+        nr -= bits_to_set;
+        bits_to_set = BITS_PER_LONG;
+        mask_to_set = ~0UL;
+        p++;
+    }
+    if (nr) {
+        mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+        *p |= mask_to_set;
+    }
+}
+
+void bitmap_clear(unsigned long *map, int start, int nr)
+{
+    unsigned long *p = map + BIT_WORD(start);
+    const int size = start + nr;
+    int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+    unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+    while (nr - bits_to_clear >= 0) {
+        *p &= ~mask_to_clear;
+        nr -= bits_to_clear;
+        bits_to_clear = BITS_PER_LONG;
+        mask_to_clear = ~0UL;
+        p++;
+    }
+    if (nr) {
+        mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+        *p &= ~mask_to_clear;
+    }
+}
+
+#define ALIGN_MASK(x,mask)      (((x)+(mask))&~(mask))
+
+/**
+ * bitmap_find_next_zero_area - find a contiguous aligned zero area
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @align_mask: Alignment mask for zero area
+ *
+ * The @align_mask should be one less than a power of 2; the effect is that
+ * the bit offset of all zero areas this function finds is multiples of that
+ * power of 2. A @align_mask of 0 means no alignment is required.
+ */
+unsigned long bitmap_find_next_zero_area(unsigned long *map,
+					 unsigned long size,
+					 unsigned long start,
+					 unsigned int nr,
+					 unsigned long align_mask)
+{
+    unsigned long index, end, i;
+again:
+    index = find_next_zero_bit(map, size, start);
+
+    /* Align allocation */
+    index = ALIGN_MASK(index, align_mask);
+
+    end = index + nr;
+    if (end > size) {
+        return end;
+    }
+    i = find_next_bit(map, end, index);
+    if (i < end) {
+        start = i + 1;
+        goto again;
+    }
+    return index;
+}
+
+int slow_bitmap_intersects(const unsigned long *bitmap1,
+                           const unsigned long *bitmap2, int bits)
+{
+    int k, lim = bits/BITS_PER_LONG;
+
+    for (k = 0; k < lim; ++k) {
+        if (bitmap1[k] & bitmap2[k]) {
+            return 1;
+        }
+    }
+
+    if (bits % BITS_PER_LONG) {
+        if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
+            return 1;
+        }
+    }
+    return 0;
+}
diff --git a/bitmap.h b/bitmap.h
new file mode 100644
index 0000000..efd5d3a
--- /dev/null
+++ b/bitmap.h
@@ -0,0 +1,222 @@
+/*
+ * Bitmap Module
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include "qemu-common.h"
+#include "bitops.h"
+
+/*
+ * The available bitmap operations and their rough meaning in the
+ * case that the bitmap is a single unsigned long are thus:
+ *
+ * Note that nbits should be always a compile time evaluable constant.
+ * Otherwise many inlines will generate horrible code.
+ *
+ * bitmap_zero(dst, nbits)			*dst = 0UL
+ * bitmap_fill(dst, nbits)			*dst = ~0UL
+ * bitmap_copy(dst, src, nbits)			*dst = *src
+ * bitmap_and(dst, src1, src2, nbits)		*dst = *src1 & *src2
+ * bitmap_or(dst, src1, src2, nbits)		*dst = *src1 | *src2
+ * bitmap_xor(dst, src1, src2, nbits)		*dst = *src1 ^ *src2
+ * bitmap_andnot(dst, src1, src2, nbits)	*dst = *src1 & ~(*src2)
+ * bitmap_complement(dst, src, nbits)		*dst = ~(*src)
+ * bitmap_equal(src1, src2, nbits)		Are *src1 and *src2 equal?
+ * bitmap_intersects(src1, src2, nbits) 	Do *src1 and *src2 overlap?
+ * bitmap_empty(src, nbits)			Are all bits zero in *src?
+ * bitmap_full(src, nbits)			Are all bits set in *src?
+ * bitmap_set(dst, pos, nbits)			Set specified bit area
+ * bitmap_clear(dst, pos, nbits)		Clear specified bit area
+ * bitmap_find_next_zero_area(buf, len, pos, n, mask)	Find bit free area
+ */
+
+/*
+ * Also the following operations apply to bitmaps.
+ *
+ * set_bit(bit, addr)			*addr |= bit
+ * clear_bit(bit, addr)			*addr &= ~bit
+ * change_bit(bit, addr)		*addr ^= bit
+ * test_bit(bit, addr)			Is bit set in *addr?
+ * test_and_set_bit(bit, addr)		Set bit and return old value
+ * test_and_clear_bit(bit, addr)	Clear bit and return old value
+ * test_and_change_bit(bit, addr)	Change bit and return old value
+ * find_first_zero_bit(addr, nbits)	Position first zero bit in *addr
+ * find_first_bit(addr, nbits)		Position first set bit in *addr
+ * find_next_zero_bit(addr, nbits, bit)	Position next zero bit in *addr >= bit
+ * find_next_bit(addr, nbits, bit)	Position next set bit in *addr >= bit
+ */
+
+#define BITMAP_LAST_WORD_MASK(nbits)                                    \
+    (                                                                   \
+        ((nbits) % BITS_PER_LONG) ?                                     \
+        (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL                       \
+        )
+
+#define DECLARE_BITMAP(name,bits)                  \
+	unsigned long name[BITS_TO_LONGS(bits)]
+
+#define small_nbits(nbits)                      \
+	((nbits) <= BITS_PER_LONG)
+
+int slow_bitmap_empty(const unsigned long *bitmap, int bits);
+int slow_bitmap_full(const unsigned long *bitmap, int bits);
+int slow_bitmap_equal(const unsigned long *bitmap1,
+                   const unsigned long *bitmap2, int bits);
+void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
+                         int bits);
+void slow_bitmap_shift_right(unsigned long *dst,
+                          const unsigned long *src, int shift, int bits);
+void slow_bitmap_shift_left(unsigned long *dst,
+                         const unsigned long *src, int shift, int bits);
+int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+                 const unsigned long *bitmap2, int bits);
+void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+                 const unsigned long *bitmap2, int bits);
+void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+                  const unsigned long *bitmap2, int bits);
+int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+                    const unsigned long *bitmap2, int bits);
+int slow_bitmap_intersects(const unsigned long *bitmap1,
+			const unsigned long *bitmap2, int bits);
+
+static inline unsigned long *bitmap_new(int nbits)
+{
+    int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+    return qemu_mallocz(len);
+}
+
+static inline void bitmap_zero(unsigned long *dst, int nbits)
+{
+    if (small_nbits(nbits)) {
+        *dst = 0UL;
+    } else {
+        int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+        memset(dst, 0, len);
+    }
+}
+
+static inline void bitmap_fill(unsigned long *dst, int nbits)
+{
+    size_t nlongs = BITS_TO_LONGS(nbits);
+    if (!small_nbits(nbits)) {
+        int len = (nlongs - 1) * sizeof(unsigned long);
+        memset(dst, 0xff,  len);
+    }
+    dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
+}
+
+static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
+                               int nbits)
+{
+    if (small_nbits(nbits)) {
+        *dst = *src;
+    } else {
+        int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+        memcpy(dst, src, len);
+    }
+}
+
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
+                             const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return (*dst = *src1 & *src2) != 0;
+    }
+    return slow_bitmap_and(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
+			const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        *dst = *src1 | *src2;
+    } else {
+        slow_bitmap_or(dst, src1, src2, nbits);
+    }
+}
+
+static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
+			const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        *dst = *src1 ^ *src2;
+    } else {
+        slow_bitmap_xor(dst, src1, src2, nbits);
+    }
+}
+
+static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+			const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return (*dst = *src1 & ~(*src2)) != 0;
+    }
+    return slow_bitmap_andnot(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
+			int nbits)
+{
+    if (small_nbits(nbits)) {
+        *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
+    } else {
+        slow_bitmap_complement(dst, src, nbits);
+    }
+}
+
+static inline int bitmap_equal(const unsigned long *src1,
+			const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
+    } else {
+        return slow_bitmap_equal(src1, src2, nbits);
+    }
+}
+
+static inline int bitmap_empty(const unsigned long *src, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
+    } else {
+        return slow_bitmap_empty(src, nbits);
+    }
+}
+
+static inline int bitmap_full(const unsigned long *src, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
+    } else {
+        return slow_bitmap_full(src, nbits);
+    }
+}
+
+static inline int bitmap_intersects(const unsigned long *src1,
+			const unsigned long *src2, int nbits)
+{
+    if (small_nbits(nbits)) {
+        return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+    } else {
+        return slow_bitmap_intersects(src1, src2, nbits);
+    }
+}
+
+void bitmap_set(unsigned long *map, int i, int len);
+void bitmap_clear(unsigned long *map, int start, int nr);
+unsigned long bitmap_find_next_zero_area(unsigned long *map,
+					 unsigned long size,
+					 unsigned long start,
+					 unsigned int nr,
+					 unsigned long align_mask);
+
+#endif /* BITMAP_H */
diff --git a/bitops.c b/bitops.c
new file mode 100644
index 0000000..d9de71f
--- /dev/null
+++ b/bitops.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells at redhat.com)
+ * Copyright (C) 2008 IBM Corporation
+ * Written by Rusty Russell <rusty at rustcorp.com.au>
+ * (Inspired by David Howell's find_next_bit implementation)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "bitops.h"
+
+#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
+
+/*
+ * Find the next set bit in a memory region.
+ */
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+			    unsigned long offset)
+{
+    const unsigned long *p = addr + BITOP_WORD(offset);
+    unsigned long result = offset & ~(BITS_PER_LONG-1);
+    unsigned long tmp;
+
+    if (offset >= size) {
+        return size;
+    }
+    size -= result;
+    offset %= BITS_PER_LONG;
+    if (offset) {
+        tmp = *(p++);
+        tmp &= (~0UL << offset);
+        if (size < BITS_PER_LONG) {
+            goto found_first;
+        }
+        if (tmp) {
+            goto found_middle;
+        }
+        size -= BITS_PER_LONG;
+        result += BITS_PER_LONG;
+    }
+    while (size & ~(BITS_PER_LONG-1)) {
+        if ((tmp = *(p++))) {
+            goto found_middle;
+        }
+        result += BITS_PER_LONG;
+        size -= BITS_PER_LONG;
+    }
+    if (!size) {
+        return result;
+    }
+    tmp = *p;
+
+found_first:
+    tmp &= (~0UL >> (BITS_PER_LONG - size));
+    if (tmp == 0UL) {		/* Are any bits set? */
+        return result + size;	/* Nope. */
+    }
+found_middle:
+    return result + bitops_ffsl(tmp);
+}
+
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+				 unsigned long offset)
+{
+    const unsigned long *p = addr + BITOP_WORD(offset);
+    unsigned long result = offset & ~(BITS_PER_LONG-1);
+    unsigned long tmp;
+
+    if (offset >= size) {
+        return size;
+    }
+    size -= result;
+    offset %= BITS_PER_LONG;
+    if (offset) {
+        tmp = *(p++);
+        tmp |= ~0UL >> (BITS_PER_LONG - offset);
+        if (size < BITS_PER_LONG) {
+            goto found_first;
+        }
+        if (~tmp) {
+            goto found_middle;
+        }
+        size -= BITS_PER_LONG;
+        result += BITS_PER_LONG;
+    }
+    while (size & ~(BITS_PER_LONG-1)) {
+        if (~(tmp = *(p++))) {
+            goto found_middle;
+        }
+        result += BITS_PER_LONG;
+        size -= BITS_PER_LONG;
+    }
+    if (!size) {
+        return result;
+    }
+    tmp = *p;
+
+found_first:
+    tmp |= ~0UL << size;
+    if (tmp == ~0UL) {	/* Are any bits zero? */
+        return result + size;	/* Nope. */
+    }
+found_middle:
+    return result + ffz(tmp);
+}
+
+unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
+{
+    unsigned long words;
+    unsigned long tmp;
+
+    /* Start at final word. */
+    words = size / BITS_PER_LONG;
+
+    /* Partial final word? */
+    if (size & (BITS_PER_LONG-1)) {
+        tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
+                                       - (size & (BITS_PER_LONG-1)))));
+        if (tmp) {
+            goto found;
+        }
+    }
+
+    while (words) {
+        tmp = addr[--words];
+        if (tmp) {
+        found:
+            return words * BITS_PER_LONG + bitops_flsl(tmp);
+        }
+    }
+
+    /* Not found */
+    return size;
+}
diff --git a/bitops.h b/bitops.h
new file mode 100644
index 0000000..ae7bcb1
--- /dev/null
+++ b/bitops.h
@@ -0,0 +1,272 @@
+/*
+ * Bitops Module
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#include "qemu-common.h"
+
+#define BITS_PER_BYTE           CHAR_BIT
+#define BITS_PER_LONG           (sizeof (unsigned long) * BITS_PER_BYTE)
+
+#define BIT(nr)			(1UL << (nr))
+#define BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
+#define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+
+/**
+ * bitops_ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static unsigned long bitops_ffsl(unsigned long word)
+{
+	int num = 0;
+
+#if LONG_MAX > 0x7FFFFFFF
+	if ((word & 0xffffffff) == 0) {
+		num += 32;
+		word >>= 32;
+	}
+#endif
+	if ((word & 0xffff) == 0) {
+		num += 16;
+		word >>= 16;
+	}
+	if ((word & 0xff) == 0) {
+		num += 8;
+		word >>= 8;
+	}
+	if ((word & 0xf) == 0) {
+		num += 4;
+		word >>= 4;
+	}
+	if ((word & 0x3) == 0) {
+		num += 2;
+		word >>= 2;
+	}
+	if ((word & 0x1) == 0) {
+		num += 1;
+        }
+	return num;
+}
+
+/**
+ * bitops_fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static __always_inline unsigned long bitops_flsl(unsigned long word)
+{
+	int num = BITS_PER_LONG - 1;
+
+#if LONG_MAX > 0x7FFFFFFF
+	if (!(word & (~0ul << 32))) {
+		num -= 32;
+		word <<= 32;
+	}
+#endif
+	if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
+		num -= 16;
+		word <<= 16;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
+		num -= 8;
+		word <<= 8;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
+		num -= 4;
+		word <<= 4;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
+		num -= 2;
+
+		word <<= 2;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-1))))
+		num -= 1;
+	return num;
+}
+
+/**
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+    return bitops_ffsl(~word);
+}
+
+/**
+ * set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p  |= mask;
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p &= ~mask;
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p ^= mask;
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old = *p;
+
+	*p = old | mask;
+	return (old & mask) != 0;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old = *p;
+
+	*p = old & ~mask;
+	return (old & mask) != 0;
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old;
+
+	*p = old ^ mask;
+	return (old & mask) != 0;
+}
+
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+/**
+ * find_last_bit - find the last set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit, or size.
+ */
+unsigned long find_last_bit(const unsigned long *addr,
+                            unsigned long size);
+
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
+unsigned long find_next_bit(const unsigned long *addr,
+				   unsigned long size, unsigned long offset);
+
+/**
+ * find_next_zero_bit - find the next cleared bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
+
+unsigned long find_next_zero_bit(const unsigned long *addr,
+                                 unsigned long size,
+                                 unsigned long offset);
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit.
+ */
+static inline unsigned long find_first_bit(const unsigned long *addr,
+                                           unsigned long size)
+{
+    return find_next_bit(addr, size, 0);
+}
+
+/**
+ * find_first_zero_bit - find the first cleared bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first cleared bit.
+ */
+static inline unsigned long find_first_zero_bit(const unsigned long *addr,
+                                                unsigned long size)
+{
+    return find_next_zero_bit(addr, size, 0);
+}
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+    unsigned long count;
+
+    for (count = 0; w; w >>= 1) {
+        count += w & 1;
+    }
+    return count;
+}
+
+#endif
diff --git a/osdep.h b/osdep.h
index 8bd30d7..27eedcf 100644
--- a/osdep.h
+++ b/osdep.h
@@ -57,6 +57,10 @@
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
 
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#endif
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #endif
commit 207f328afc2137d422f59293ba37b8be5d3e1617
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:03 2011 +0100

    vnc: fix lossy rect refreshing
    
    The for loop in send_lossy_rect was totally wrong, and we can't
    call vnc_set_bits() because it does not really do what it should.
    Use vnc_set_bit() directly instead.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 9920c0e..8c7cb0d 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2297,8 +2297,8 @@ void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h)
     x /= VNC_STAT_RECT;
     y /= VNC_STAT_RECT;
 
-    for (j = y; j <= y + h; j++) {
-        for (i = x; i <= x + w; i++) {
+    for (j = y; j <= h; j++) {
+        for (i = x; i <= w; i++) {
             vs->lossy_rect[j][i] = 1;
         }
     }
@@ -2315,7 +2315,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
     x = x / VNC_STAT_RECT * VNC_STAT_RECT;
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
-        int j;
+        int j, i;
 
         /* kernel send buffers are full -> refresh later */
         if (vs->output.offset) {
@@ -2325,12 +2325,16 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
         if (!vs->lossy_rect[sty][stx]) {
             continue;
         }
+
         vs->lossy_rect[sty][stx] = 0;
         for (j = 0; j < VNC_STAT_RECT; ++j) {
-            vnc_set_bits(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
+            for (i = x / 16; i < VNC_STAT_RECT / 16 + x / 16; ++i) {
+                vnc_set_bit(vs->dirty[y + j], i);
+            }
         }
         has_dirty++;
     }
+
     return has_dirty;
 }
 
commit 368d25881c94f9e09ef19a3d93e8fec797dbcd05
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:02 2011 +0100

    vnc: fix uint8_t comparisons with negative values
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index ad9a9a8..81024d5 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -1546,7 +1546,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     vnc_tight_stop(vs);
 
 #ifdef CONFIG_VNC_JPEG
-    if (vs->tight.quality != -1) {
+    if (vs->tight.quality != (uint8_t)-1) {
         double freq = vnc_update_freq(vs, x, y, w, h);
 
         if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) {
@@ -1711,7 +1711,7 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y,
         vs->tight.pixel24 = false;
     }
 
-    if (vs->tight.quality != -1) {
+    if (vs->tight.quality != (uint8_t)-1) {
         double freq = vnc_update_freq(vs, x, y, w, h);
 
         if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) {
diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c
index 016a406..917d384 100644
--- a/ui/vnc-enc-zrle.c
+++ b/ui/vnc-enc-zrle.c
@@ -260,7 +260,8 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
     int zywrle_level;
 
     if (vs->zrle.type == VNC_ENCODING_ZYWRLE) {
-        if (!vs->vd->lossy || vs->tight.quality < 0 || vs->tight.quality == 9) {
+        if (!vs->vd->lossy || vs->tight.quality == (uint8_t)-1
+            || vs->tight.quality == 9) {
             zywrle_level = 0;
             vs->zrle.type = VNC_ENCODING_ZRLE;
         } else if (vs->tight.quality < 3) {
commit 148954faca586c42e5a4b06bc3ac67bd44e7fd83
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:01 2011 +0100

    vnc: Add ZRLE and ZYWRLE encodings.
    
    Add ZRLE [1] and ZYWRLE [2] encodings. The code is inspire^W stolen
    from libvncserver (again), but have been rewriten to match QEMU coding
    style.
    
    [1] http://www.realvnc.com/docs/rfbproto.pdf
    [2] http://micro-vnc.jp/research/remote_desktop_ng/ZYWRLE/publications/
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index c144df1..2ac995b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -129,6 +129,7 @@ ui-obj-$(CONFIG_CURSES) += curses.o
 ui-obj-y += vnc.o d3des.o
 ui-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
 ui-obj-y += vnc-enc-tight.o vnc-palette.o
+ui-obj-y += vnc-enc-zrle.o
 ui-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 ui-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
 ui-obj-$(CONFIG_COCOA) += cocoa.o
diff --git a/ui/vnc-enc-zrle-template.c b/ui/vnc-enc-zrle-template.c
new file mode 100644
index 0000000..70ae624
--- /dev/null
+++ b/ui/vnc-enc-zrle-template.c
@@ -0,0 +1,263 @@
+/*
+ * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE)
+ *
+ * From libvncserver/libvncserver/zrleencodetemplate.c
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Before including this file, you must define a number of CPP macros.
+ *
+ * ZRLE_BPP should be 8, 16 or 32 depending on the bits per pixel.
+ *
+ * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
+ * bigger than the largest tile of pixel data, since the ZRLE encoding
+ * algorithm writes to the position one past the end of the pixel data.
+ */
+
+
+#include <assert.h>
+
+#undef ZRLE_ENDIAN_SUFFIX
+
+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
+#define ZRLE_ENDIAN_SUFFIX le
+#elif ZYWRLE_ENDIAN == ENDIAN_BIG
+#define ZRLE_ENDIAN_SUFFIX be
+#else
+#define ZRLE_ENDIAN_SUFFIX ne
+#endif
+
+#ifndef ZRLE_CONCAT
+#define ZRLE_CONCAT_I(a, b)    a##b
+#define ZRLE_CONCAT2(a, b)     ZRLE_CONCAT_I(a, b)
+#define ZRLE_CONCAT3(a, b, c)  ZRLE_CONCAT2(a, ZRLE_CONCAT2(b, c))
+#endif
+
+#ifdef ZRLE_COMPACT_PIXEL
+#define ZRLE_ENCODE_SUFFIX   ZRLE_CONCAT2(ZRLE_COMPACT_PIXEL,ZRLE_ENDIAN_SUFFIX)
+#define ZRLE_WRITE_SUFFIX    ZRLE_COMPACT_PIXEL
+#define ZRLE_PIXEL           ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
+#define ZRLE_BPP_OUT         24
+#elif ZRLE_BPP == 15
+#define ZRLE_ENCODE_SUFFIX   ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
+#define ZRLE_WRITE_SUFFIX    16
+#define ZRLE_PIXEL           uint16_t
+#define ZRLE_BPP_OUT         16
+#else
+#define ZRLE_ENCODE_SUFFIX   ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
+#define ZRLE_WRITE_SUFFIX    ZRLE_BPP
+#define ZRLE_BPP_OUT         ZRLE_BPP
+#define ZRLE_PIXEL           ZRLE_CONCAT3(uint,ZRLE_BPP,_t)
+#endif
+
+#define ZRLE_WRITE_PIXEL     ZRLE_CONCAT2(zrle_write_u,       ZRLE_WRITE_SUFFIX)
+#define ZRLE_ENCODE          ZRLE_CONCAT2(zrle_encode_,      ZRLE_ENCODE_SUFFIX)
+#define ZRLE_ENCODE_TILE     ZRLE_CONCAT2(zrle_encode_tile,  ZRLE_ENCODE_SUFFIX)
+#define ZRLE_WRITE_PALETTE   ZRLE_CONCAT2(zrle_write_palette,ZRLE_ENCODE_SUFFIX)
+
+static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h,
+                             int zywrle_level);
+
+#if ZRLE_BPP != 8
+#include "vnc-enc-zywrle-template.c"
+#endif
+
+
+static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h,
+                        int zywrle_level)
+{
+    int ty;
+
+    for (ty = y; ty < y + h; ty += VNC_ZRLE_TILE_HEIGHT) {
+
+        int tx, th;
+
+        th = MIN(VNC_ZRLE_TILE_HEIGHT, y + h - ty);
+
+        for (tx = x; tx < x + w; tx += VNC_ZRLE_TILE_WIDTH) {
+            int tw;
+            ZRLE_PIXEL *buf;
+
+            tw = MIN(VNC_ZRLE_TILE_WIDTH, x + w - tx);
+
+            buf = zrle_convert_fb(vs, tx, ty, tw, th, ZRLE_BPP);
+            ZRLE_ENCODE_TILE(vs, buf, tw, th, zywrle_level);
+        }
+    }
+}
+
+static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h,
+                             int zywrle_level)
+{
+    VncPalette *palette = &vs->zrle.palette;
+
+    int runs = 0;
+    int single_pixels = 0;
+
+    bool use_rle;
+    bool use_palette;
+
+    int i;
+
+    ZRLE_PIXEL *ptr = data;
+    ZRLE_PIXEL *end = ptr + h * w;
+    *end = ~*(end-1); /* one past the end is different so the while loop ends */
+
+    /* Real limit is 127 but we wan't a way to know if there is more than 127 */
+    palette_init(palette, 256, ZRLE_BPP);
+
+    while (ptr < end) {
+        ZRLE_PIXEL pix = *ptr;
+        if (*++ptr != pix) { /* FIXME */
+            single_pixels++;
+        } else {
+            while (*++ptr == pix) ;
+            runs++;
+        }
+        palette_put(palette, pix);
+    }
+
+    /* Solid tile is a special case */
+
+    if (palette_size(palette) == 1) {
+        bool found;
+
+        vnc_write_u8(vs, 1);
+        ZRLE_WRITE_PIXEL(vs, palette_color(palette, 0, &found));
+        return;
+    }
+
+    zrle_choose_palette_rle(vs, w, h, palette, ZRLE_BPP_OUT,
+                            runs, single_pixels, zywrle_level,
+                            &use_rle, &use_palette);
+
+    if (!use_palette) {
+        vnc_write_u8(vs, (use_rle ? 128 : 0));
+    } else {
+        uint32_t colors[VNC_PALETTE_MAX_SIZE];
+        size_t size = palette_size(palette);
+
+        vnc_write_u8(vs, (use_rle ? 128 : 0) | size);
+        palette_fill(palette, colors);
+
+        for (i = 0; i < size; i++) {
+            ZRLE_WRITE_PIXEL(vs, colors[i]);
+        }
+    }
+
+    if (use_rle) {
+        ZRLE_PIXEL *ptr = data;
+        ZRLE_PIXEL *end = ptr + w * h;
+        ZRLE_PIXEL *run_start;
+        ZRLE_PIXEL pix;
+
+        while (ptr < end) {
+            int len;
+            int index = 0;
+
+            run_start = ptr;
+            pix = *ptr++;
+
+            while (*ptr == pix && ptr < end) {
+                ptr++;
+            }
+
+            len = ptr - run_start;
+
+            if (use_palette)
+                index = palette_idx(palette, pix);
+
+            if (len <= 2 && use_palette) {
+                if (len == 2) {
+                    vnc_write_u8(vs, index);
+                }
+                vnc_write_u8(vs, index);
+                continue;
+            }
+            if (use_palette) {
+                vnc_write_u8(vs, index | 128);
+            } else {
+                ZRLE_WRITE_PIXEL(vs, pix);
+            }
+
+            len -= 1;
+
+            while (len >= 255) {
+                vnc_write_u8(vs, 255);
+                len -= 255;
+            }
+
+            vnc_write_u8(vs, len);
+        }
+    } else if (use_palette) { /* no RLE */
+        int bppp;
+        ZRLE_PIXEL *ptr = data;
+
+        /* packed pixels */
+
+        assert (palette_size(palette) < 17);
+
+        bppp = bits_per_packed_pixel[palette_size(palette)-1];
+
+        for (i = 0; i < h; i++) {
+            uint8_t nbits = 0;
+            uint8_t byte = 0;
+
+            ZRLE_PIXEL *eol = ptr + w;
+
+            while (ptr < eol) {
+                ZRLE_PIXEL pix = *ptr++;
+                uint8_t index = palette_idx(palette, pix);
+
+                byte = (byte << bppp) | index;
+                nbits += bppp;
+                if (nbits >= 8) {
+                    vnc_write_u8(vs, byte);
+                    nbits = 0;
+                }
+            }
+            if (nbits > 0) {
+                byte <<= 8 - nbits;
+                vnc_write_u8(vs, byte);
+            }
+        }
+    } else {
+
+        /* raw */
+
+#if ZRLE_BPP != 8
+        if (zywrle_level > 0 && !(zywrle_level & 0x80)) {
+            ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, vs->zywrle.buf);
+            ZRLE_ENCODE_TILE(vs, data, w, h, zywrle_level | 0x80);
+        }
+        else
+#endif
+        {
+#ifdef ZRLE_COMPACT_PIXEL
+            ZRLE_PIXEL *ptr;
+
+            for (ptr = data; ptr < data + w * h; ptr++) {
+                ZRLE_WRITE_PIXEL(vs, *ptr);
+            }
+#else
+            vnc_write(vs, data, w * h * (ZRLE_BPP / 8));
+#endif
+        }
+    }
+}
+
+#undef ZRLE_PIXEL
+#undef ZRLE_WRITE_PIXEL
+#undef ZRLE_ENCODE
+#undef ZRLE_ENCODE_TILE
+#undef ZYWRLE_ENCODE_TILE
+#undef ZRLE_BPP_OUT
+#undef ZRLE_WRITE_SUFFIX
+#undef ZRLE_ENCODE_SUFFIX
diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c
new file mode 100644
index 0000000..016a406
--- /dev/null
+++ b/ui/vnc-enc-zrle.c
@@ -0,0 +1,365 @@
+/*
+ * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE)
+ *
+ * From libvncserver/libvncserver/zrle.c
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vnc.h"
+#include "vnc-enc-zrle.h"
+
+static const int bits_per_packed_pixel[] = {
+  0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+
+static void vnc_zrle_start(VncState *vs)
+{
+    buffer_reset(&vs->zrle.zrle);
+
+    /* make the output buffer be the zlib buffer, so we can compress it later */
+    vs->zrle.tmp = vs->output;
+    vs->output = vs->zrle.zrle;
+}
+
+static void vnc_zrle_stop(VncState *vs)
+{
+    /* switch back to normal output/zlib buffers */
+    vs->zrle.zrle = vs->output;
+    vs->output = vs->zrle.tmp;
+}
+
+static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h,
+                             int bpp)
+{
+    Buffer tmp;
+
+    buffer_reset(&vs->zrle.fb);
+    buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp);
+
+    tmp = vs->output;
+    vs->output = vs->zrle.fb;
+
+    vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+
+    vs->zrle.fb = vs->output;
+    vs->output = tmp;
+    return vs->zrle.fb.buffer;
+}
+
+static int zrle_compress_data(VncState *vs, int level)
+{
+    z_streamp zstream = &vs->zrle.stream;
+
+    buffer_reset(&vs->zrle.zlib);
+
+    if (zstream->opaque != vs) {
+        int err;
+
+        zstream->zalloc = vnc_zlib_zalloc;
+        zstream->zfree = vnc_zlib_zfree;
+
+        err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS,
+                           MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+
+        if (err != Z_OK) {
+            fprintf(stderr, "VNC: error initializing zlib\n");
+            return -1;
+        }
+
+        zstream->opaque = vs;
+    }
+
+    /* reserve memory in output buffer */
+    buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64);
+
+    /* set pointers */
+    zstream->next_in = vs->zrle.zrle.buffer;
+    zstream->avail_in = vs->zrle.zrle.offset;
+    zstream->next_out = vs->zrle.zlib.buffer + vs->zrle.zlib.offset;
+    zstream->avail_out = vs->zrle.zlib.capacity - vs->zrle.zlib.offset;
+    zstream->data_type = Z_BINARY;
+
+    /* start encoding */
+    if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
+        fprintf(stderr, "VNC: error during zrle compression\n");
+        return -1;
+    }
+
+    vs->zrle.zlib.offset = vs->zrle.zlib.capacity - zstream->avail_out;
+    return vs->zrle.zlib.offset;
+}
+
+/* Try to work out whether to use RLE and/or a palette.  We do this by
+ * estimating the number of bytes which will be generated and picking the
+ * method which results in the fewest bytes.  Of course this may not result
+ * in the fewest bytes after compression... */
+static void zrle_choose_palette_rle(VncState *vs, int w, int h,
+                                    VncPalette *palette, int bpp_out,
+                                    int runs, int single_pixels,
+                                    int zywrle_level,
+                                    bool *use_rle, bool *use_palette)
+{
+    size_t estimated_bytes;
+    size_t plain_rle_bytes;
+
+    *use_palette = *use_rle = false;
+
+    estimated_bytes = w * h * (bpp_out / 8); /* start assuming raw */
+
+    if (bpp_out != 8) {
+        if (zywrle_level > 0 && !(zywrle_level & 0x80))
+            estimated_bytes >>= zywrle_level;
+    }
+
+    plain_rle_bytes = ((bpp_out / 8) + 1) * (runs + single_pixels);
+
+    if (plain_rle_bytes < estimated_bytes) {
+        *use_rle = true;
+        estimated_bytes = plain_rle_bytes;
+    }
+
+    if (palette_size(palette) < 128) {
+        int palette_rle_bytes;
+
+        palette_rle_bytes = (bpp_out / 8) * palette_size(palette);
+        palette_rle_bytes += 2 * runs + single_pixels;
+
+        if (palette_rle_bytes < estimated_bytes) {
+            *use_rle = true;
+            *use_palette = true;
+            estimated_bytes = palette_rle_bytes;
+        }
+
+        if (palette_size(palette) < 17) {
+            int packed_bytes;
+
+            packed_bytes = (bpp_out / 8) * palette_size(palette);
+            packed_bytes += w * h *
+                bits_per_packed_pixel[palette_size(palette)-1] / 8;
+
+            if (packed_bytes < estimated_bytes) {
+                *use_rle = false;
+                *use_palette = true;
+                estimated_bytes = packed_bytes;
+            }
+        }
+    }
+}
+
+static void zrle_write_u32(VncState *vs, uint32_t value)
+{
+    vnc_write(vs, (uint8_t *)&value, 4);
+}
+
+static void zrle_write_u24a(VncState *vs, uint32_t value)
+{
+    vnc_write(vs, (uint8_t *)&value, 3);
+}
+
+static void zrle_write_u24b(VncState *vs, uint32_t value)
+{
+    vnc_write(vs, ((uint8_t *)&value) + 1, 3);
+}
+
+static void zrle_write_u16(VncState *vs, uint16_t value)
+{
+    vnc_write(vs, (uint8_t *)&value, 2);
+}
+
+static void zrle_write_u8(VncState *vs, uint8_t value)
+{
+    vnc_write_u8(vs, value);
+}
+
+#define ENDIAN_LITTLE 0
+#define ENDIAN_BIG    1
+#define ENDIAN_NO     2
+
+#define ZRLE_BPP 8
+#define ZYWRLE_ENDIAN ENDIAN_NO
+#include "vnc-enc-zrle-template.c"
+#undef ZRLE_BPP
+
+#define ZRLE_BPP 15
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#include "vnc-enc-zrle-template.c"
+
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_BIG
+#include "vnc-enc-zrle-template.c"
+
+#undef ZRLE_BPP
+#define ZRLE_BPP 16
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#include "vnc-enc-zrle-template.c"
+
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_BIG
+#include "vnc-enc-zrle-template.c"
+
+#undef ZRLE_BPP
+#define ZRLE_BPP 32
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#include "vnc-enc-zrle-template.c"
+
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_BIG
+#include "vnc-enc-zrle-template.c"
+
+#define ZRLE_COMPACT_PIXEL 24a
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#include "vnc-enc-zrle-template.c"
+
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_BIG
+#include "vnc-enc-zrle-template.c"
+
+#undef ZRLE_COMPACT_PIXEL
+#define ZRLE_COMPACT_PIXEL 24b
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#include "vnc-enc-zrle-template.c"
+
+#undef ZYWRLE_ENDIAN
+#define ZYWRLE_ENDIAN ENDIAN_BIG
+#include "vnc-enc-zrle-template.c"
+#undef ZRLE_COMPACT_PIXEL
+#undef ZRLE_BPP
+
+static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
+                                        int w, int h)
+{
+    bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG);
+    size_t bytes;
+    int zywrle_level;
+
+    if (vs->zrle.type == VNC_ENCODING_ZYWRLE) {
+        if (!vs->vd->lossy || vs->tight.quality < 0 || vs->tight.quality == 9) {
+            zywrle_level = 0;
+            vs->zrle.type = VNC_ENCODING_ZRLE;
+        } else if (vs->tight.quality < 3) {
+            zywrle_level = 3;
+        } else if (vs->tight.quality < 6) {
+            zywrle_level = 2;
+        } else {
+            zywrle_level = 1;
+        }
+    } else {
+        zywrle_level = 0;
+    }
+
+    vnc_zrle_start(vs);
+
+    switch(vs->clientds.pf.bytes_per_pixel) {
+    case 1:
+        zrle_encode_8ne(vs, x, y, w, h, zywrle_level);
+        break;
+
+    case 2:
+        if (vs->clientds.pf.gmax > 0x1F) {
+            if (be) {
+                zrle_encode_16be(vs, x, y, w, h, zywrle_level);
+            } else {
+                zrle_encode_16le(vs, x, y, w, h, zywrle_level);
+            }
+        } else {
+            if (be) {
+                zrle_encode_15be(vs, x, y, w, h, zywrle_level);
+            } else {
+                zrle_encode_15le(vs, x, y, w, h, zywrle_level);
+            }
+        }
+        break;
+
+    case 4:
+    {
+        bool fits_in_ls3bytes;
+        bool fits_in_ms3bytes;
+
+        fits_in_ls3bytes =
+            ((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) &&
+             (vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) &&
+             (vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24));
+
+        fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 &&
+                            vs->clientds.pf.gshift > 7 &&
+                            vs->clientds.pf.bshift > 7);
+
+        if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) {
+            if (be) {
+                zrle_encode_24abe(vs, x, y, w, h, zywrle_level);
+            } else {
+                zrle_encode_24ale(vs, x, y, w, h, zywrle_level);
+          }
+        } else if ((fits_in_ls3bytes && be) || (fits_in_ms3bytes && !be)) {
+            if (be) {
+                zrle_encode_24bbe(vs, x, y, w, h, zywrle_level);
+            } else {
+                zrle_encode_24ble(vs, x, y, w, h, zywrle_level);
+            }
+        } else {
+            if (be) {
+                zrle_encode_32be(vs, x, y, w, h, zywrle_level);
+            } else {
+                zrle_encode_32le(vs, x, y, w, h, zywrle_level);
+            }
+        }
+    }
+    break;
+    }
+
+    vnc_zrle_stop(vs);
+    bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION);
+    vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type);
+    vnc_write_u32(vs, bytes);
+    vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset);
+    return 1;
+}
+
+int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+{
+    vs->zrle.type = VNC_ENCODING_ZRLE;
+    return zrle_send_framebuffer_update(vs, x, y, w, h);
+}
+
+int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+{
+    vs->zrle.type = VNC_ENCODING_ZYWRLE;
+    return zrle_send_framebuffer_update(vs, x, y, w, h);
+}
+
+void vnc_zrle_clear(VncState *vs)
+{
+    if (vs->zrle.stream.opaque) {
+        deflateEnd(&vs->zrle.stream);
+    }
+    buffer_free(&vs->zrle.zrle);
+    buffer_free(&vs->zrle.fb);
+    buffer_free(&vs->zrle.zlib);
+}
diff --git a/ui/vnc-enc-zrle.h b/ui/vnc-enc-zrle.h
new file mode 100644
index 0000000..6b18213
--- /dev/null
+++ b/ui/vnc-enc-zrle.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU VNC display driver: Zlib Run-length Encoding (ZRLE)
+ *
+ * From libvncserver/libvncserver/zrle.c
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef VNC_ENCODING_ZRLE_H
+#define VNC_ENCODING_ZRLE_H
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * ZRLE - encoding combining Zlib compression, tiling, palettisation and
+ * run-length encoding.
+ */
+
+#define VNC_ZRLE_TILE_WIDTH  64
+#define VNC_ZRLE_TILE_HEIGHT 64
+
+#endif
diff --git a/ui/vnc-enc-zywrle-template.c b/ui/vnc-enc-zywrle-template.c
new file mode 100644
index 0000000..4cde6e4
--- /dev/null
+++ b/ui/vnc-enc-zywrle-template.c
@@ -0,0 +1,170 @@
+
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE.         *
+ *                                                                  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE.                *
+ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
+ *                                                                  *
+ * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
+ * BY Hitachi Systems & Services, Ltd.                              *
+ * (Noriaki Yamazaki, Research & Developement Center)               *
+ *                                                                  *
+ *                                                                  *
+ ********************************************************************
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Hitachi Systems & Services, Ltd. nor
+the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************/
+
+/* Change Log:
+     V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline
+	                     (Thanks Johannes Schindelin, author of LibVNC
+						  Server/Client)
+     V0.01 : 2007/02/06 : Initial release
+*/
+
+/*
+[References]
+ PLHarr:
+   Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy,
+   "An Improved N-Bit to N-Bit Reversible Haar-Like Transform,"
+   Pacific Graphics 2004, October 2004, pp. 371-380.
+ EZW:
+   Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients,
+   IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
+*/
+
+
+/* Template Macro stuffs. */
+#undef ZYWRLE_ANALYZE
+#undef ZYWRLE_SYNTHESIZE
+
+#define ZYWRLE_SUFFIX     ZRLE_CONCAT2(ZRLE_BPP,ZRLE_ENDIAN_SUFFIX)
+
+#define ZYWRLE_ANALYZE    ZRLE_CONCAT2(zywrle_analyze_,   ZYWRLE_SUFFIX)
+#define ZYWRLE_SYNTHESIZE ZRLE_CONCAT2(zywrle_synthesize_,ZYWRLE_SUFFIX)
+
+#define ZYWRLE_RGBYUV     ZRLE_CONCAT2(zywrle_rgbyuv_,    ZYWRLE_SUFFIX)
+#define ZYWRLE_YUVRGB     ZRLE_CONCAT2(zywrle_yuvrgb_,    ZYWRLE_SUFFIX)
+#define ZYWRLE_YMASK      ZRLE_CONCAT2(ZYWRLE_YMASK,      ZRLE_BPP)
+#define ZYWRLE_UVMASK     ZRLE_CONCAT2(ZYWRLE_UVMASK,     ZRLE_BPP)
+#define ZYWRLE_LOAD_PIXEL ZRLE_CONCAT2(ZYWRLE_LOAD_PIXEL, ZRLE_BPP)
+#define ZYWRLE_SAVE_PIXEL ZRLE_CONCAT2(ZYWRLE_SAVE_PIXEL, ZRLE_BPP)
+
+/* Packing/Unpacking pixel stuffs.
+   Endian conversion stuffs. */
+#undef S_0
+#undef S_1
+#undef L_0
+#undef L_1
+#undef L_2
+
+#if ZYWRLE_ENDIAN == ENDIAN_BIG
+#  define S_0	1
+#  define S_1	0
+#  define L_0	3
+#  define L_1	2
+#  define L_2	1
+#else
+#  define S_0	0
+#  define S_1	1
+#  define L_0	0
+#  define L_1	1
+#  define L_2	2
+#endif
+
+#define ZYWRLE_QUANTIZE
+#include "vnc-enc-zywrle.h"
+
+#ifndef ZRLE_COMPACT_PIXEL
+static inline void ZYWRLE_RGBYUV(int *buf, ZRLE_PIXEL *data,
+                                 int width, int height, int scanline)
+{
+    int r, g, b;
+    int y, u, v;
+    int *line;
+    int *end;
+
+    end = buf + height * width;
+    while (buf < end) {
+        line = buf + width;
+        while (buf < line) {
+            ZYWRLE_LOAD_PIXEL(data, r, g, b);
+            ZYWRLE_RGBYUV_(r, g, b, y, u, v, ZYWRLE_YMASK, ZYWRLE_UVMASK);
+            ZYWRLE_SAVE_COEFF(buf, v, y, u);
+            buf++;
+            data++;
+        }
+        data += scanline - width;
+    }
+}
+
+static ZRLE_PIXEL *ZYWRLE_ANALYZE(ZRLE_PIXEL *dst, ZRLE_PIXEL *src,
+                                  int w, int h, int scanline, int level,
+                                  int *buf) {
+    int l;
+    int uw = w;
+    int uh = h;
+    int *top;
+    int *end;
+    int *line;
+    ZRLE_PIXEL *p;
+    int r, g, b;
+    int s;
+    int *ph;
+
+    zywrle_calc_size(&w, &h, level);
+
+    if (w == 0 || h == 0) {
+        return NULL;
+    }
+    uw -= w;
+    uh -= h;
+
+    p = dst;
+    ZYWRLE_LOAD_UNALIGN(src,*(ZRLE_PIXEL*)top = *p;);
+    ZYWRLE_RGBYUV(buf, src, w, h, scanline);
+    wavelet(buf, w, h, level);
+    for (l = 0; l < level; l++) {
+        ZYWRLE_PACK_COEFF(buf, dst, 3, w, h, scanline, l);
+        ZYWRLE_PACK_COEFF(buf, dst, 2, w, h, scanline, l);
+        ZYWRLE_PACK_COEFF(buf, dst, 1, w, h, scanline, l);
+        if (l == level - 1) {
+            ZYWRLE_PACK_COEFF(buf, dst, 0, w, h, scanline, l);
+        }
+    }
+    ZYWRLE_SAVE_UNALIGN(dst,*dst = *(ZRLE_PIXEL*)top;);
+    return dst;
+}
+#endif  /* ZRLE_COMPACT_PIXEL */
+
+#undef ZYWRLE_RGBYUV
+#undef ZYWRLE_YUVRGB
+#undef ZYWRLE_LOAD_PIXEL
+#undef ZYWRLE_SAVE_PIXEL
diff --git a/ui/vnc-enc-zywrle.h b/ui/vnc-enc-zywrle.h
new file mode 100644
index 0000000..ac5d27a
--- /dev/null
+++ b/ui/vnc-enc-zywrle.h
@@ -0,0 +1,659 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE.         *
+ *                                                                  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE.                *
+ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
+ *                                                                  *
+ * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
+ * BY Hitachi Systems & Services, Ltd.                              *
+ * (Noriaki Yamazaki, Research & Developement Center)               *
+ *                                                                  *
+ *                                                                  *
+ ********************************************************************
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Hitachi Systems & Services, Ltd. nor
+the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************/
+
+#ifndef VNC_ENCODING_ZYWRLE_H
+#define VNC_ENCODING_ZYWRLE_H
+
+/* Tables for Coefficients filtering. */
+#ifndef ZYWRLE_QUANTIZE
+/* Type A:lower bit omitting of EZW style. */
+static const unsigned int zywrle_param[3][3]={
+	{0x0000F000, 0x00000000, 0x00000000},
+	{0x0000C000, 0x00F0F0F0, 0x00000000},
+	{0x0000C000, 0x00C0C0C0, 0x00F0F0F0},
+/*	{0x0000FF00, 0x00000000, 0x00000000},
+	{0x0000FF00, 0x00FFFFFF, 0x00000000},
+	{0x0000FF00, 0x00FFFFFF, 0x00FFFFFF}, */
+};
+#else
+/* Type B:Non liner quantization filter. */
+static const int8_t zywrle_conv[4][256]={
+{	/* bi=5, bo=5 r=0.0:PSNR=24.849 */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+},
+{	/* bi=5, bo=5 r=2.0:PSNR=74.031 */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 32,
+	32, 32, 32, 32, 32, 32, 32, 32,
+	32, 32, 32, 32, 32, 32, 32, 32,
+	48, 48, 48, 48, 48, 48, 48, 48,
+	48, 48, 48, 56, 56, 56, 56, 56,
+	56, 56, 56, 56, 64, 64, 64, 64,
+	64, 64, 64, 64, 72, 72, 72, 72,
+	72, 72, 72, 72, 80, 80, 80, 80,
+	80, 80, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 96, 96,
+	96, 96, 96, 104, 104, 104, 104, 104,
+	104, 104, 104, 104, 104, 112, 112, 112,
+	112, 112, 112, 112, 112, 112, 120, 120,
+	120, 120, 120, 120, 120, 120, 120, 120,
+	0, -120, -120, -120, -120, -120, -120, -120,
+	-120, -120, -120, -112, -112, -112, -112, -112,
+	-112, -112, -112, -112, -104, -104, -104, -104,
+	-104, -104, -104, -104, -104, -104, -96, -96,
+	-96, -96, -96, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -80,
+	-80, -80, -80, -80, -80, -72, -72, -72,
+	-72, -72, -72, -72, -72, -64, -64, -64,
+	-64, -64, -64, -64, -64, -56, -56, -56,
+	-56, -56, -56, -56, -56, -56, -48, -48,
+	-48, -48, -48, -48, -48, -48, -48, -48,
+	-48, -32, -32, -32, -32, -32, -32, -32,
+	-32, -32, -32, -32, -32, -32, -32, -32,
+	-32, -32, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+},
+{	/* bi=5, bo=4 r=2.0:PSNR=64.441 */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	48, 48, 48, 48, 48, 48, 48, 48,
+	48, 48, 48, 48, 48, 48, 48, 48,
+	48, 48, 48, 48, 48, 48, 48, 48,
+	64, 64, 64, 64, 64, 64, 64, 64,
+	64, 64, 64, 64, 64, 64, 64, 64,
+	80, 80, 80, 80, 80, 80, 80, 80,
+	80, 80, 80, 80, 80, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	104, 104, 104, 104, 104, 104, 104, 104,
+	104, 104, 104, 112, 112, 112, 112, 112,
+	112, 112, 112, 112, 120, 120, 120, 120,
+	120, 120, 120, 120, 120, 120, 120, 120,
+	0, -120, -120, -120, -120, -120, -120, -120,
+	-120, -120, -120, -120, -120, -112, -112, -112,
+	-112, -112, -112, -112, -112, -112, -104, -104,
+	-104, -104, -104, -104, -104, -104, -104, -104,
+	-104, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -80, -80, -80, -80,
+	-80, -80, -80, -80, -80, -80, -80, -80,
+	-80, -64, -64, -64, -64, -64, -64, -64,
+	-64, -64, -64, -64, -64, -64, -64, -64,
+	-64, -48, -48, -48, -48, -48, -48, -48,
+	-48, -48, -48, -48, -48, -48, -48, -48,
+	-48, -48, -48, -48, -48, -48, -48, -48,
+	-48, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+},
+{	/* bi=5, bo=2 r=2.0:PSNR=43.175 */
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	88, 88, 88, 88, 88, 88, 88, 88,
+	0, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, -88, -88, -88, -88, -88, -88, -88,
+	-88, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+}
+};
+
+static const int8_t *zywrle_param[3][3][3]={
+	{{zywrle_conv[0], zywrle_conv[2], zywrle_conv[0]},
+         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]},
+         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
+	{{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
+         {zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]},
+         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
+	{{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
+         {zywrle_conv[2], zywrle_conv[2], zywrle_conv[2]},
+         {zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]}},
+};
+#endif
+
+/*   Load/Save pixel stuffs. */
+#define ZYWRLE_YMASK15  0xFFFFFFF8
+#define ZYWRLE_UVMASK15 0xFFFFFFF8
+#define ZYWRLE_LOAD_PIXEL15(src, r, g, b)                               \
+    do {                                                                \
+	r = (((uint8_t*)src)[S_1]<< 1)& 0xF8;                           \
+	g = (((uint8_t*)src)[S_1]<< 6) | (((uint8_t*)src)[S_0]>> 2);    \
+        g &= 0xF8;                                                      \
+	b =  (((uint8_t*)src)[S_0]<< 3)& 0xF8;                          \
+    } while (0)
+
+#define ZYWRLE_SAVE_PIXEL15(dst, r, g, b)                               \
+    do {                                                                \
+	r &= 0xF8;                                                      \
+	g &= 0xF8;                                                      \
+	b &= 0xF8;                                                      \
+	((uint8_t*)dst)[S_1] = (uint8_t)((r >> 1)|(g >> 6));            \
+	((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 2))& 0xFF);    \
+    } while (0)
+
+#define ZYWRLE_YMASK16  0xFFFFFFFC
+#define ZYWRLE_UVMASK16 0xFFFFFFF8
+#define ZYWRLE_LOAD_PIXEL16(src, r, g, b)                               \
+    do {                                                                \
+	r = ((uint8_t*)src)[S_1] & 0xF8;                                \
+	g = (((uint8_t*)src)[S_1]<< 5) | (((uint8_t*)src)[S_0] >> 3);   \
+        g &= 0xFC;                                                      \
+	b = (((uint8_t*)src)[S_0]<< 3) & 0xF8;                          \
+    } while (0)
+
+#define ZYWRLE_SAVE_PIXEL16(dst, r, g,b)                                \
+    do {                                                                \
+	r &= 0xF8;                                                      \
+	g &= 0xFC;                                                      \
+	b &= 0xF8;                                                      \
+	((uint8_t*)dst)[S_1] = (uint8_t)(r | (g >> 5));                 \
+	((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 3)) & 0xFF);   \
+    } while (0)
+
+#define ZYWRLE_YMASK32  0xFFFFFFFF
+#define ZYWRLE_UVMASK32 0xFFFFFFFF
+#define ZYWRLE_LOAD_PIXEL32(src, r, g, b)     \
+    do {                                      \
+	r = ((uint8_t*)src)[L_2];             \
+	g = ((uint8_t*)src)[L_1];             \
+	b = ((uint8_t*)src)[L_0];             \
+    } while (0)
+#define ZYWRLE_SAVE_PIXEL32(dst, r, g, b)             \
+    do {                                              \
+	((uint8_t*)dst)[L_2] = (uint8_t)r;            \
+	((uint8_t*)dst)[L_1] = (uint8_t)g;            \
+	((uint8_t*)dst)[L_0] = (uint8_t)b;            \
+    } while (0)
+
+static inline void harr(int8_t *px0, int8_t *px1)
+{
+    /* Piecewise-Linear Harr(PLHarr) */
+    int x0 = (int)*px0, x1 = (int)*px1;
+    int orgx0 = x0, orgx1 = x1;
+
+    if ((x0 ^ x1) & 0x80) {
+        /* differ sign */
+        x1 += x0;
+        if (((x1 ^ orgx1) & 0x80) == 0) {
+            /* |x1| > |x0| */
+            x0 -= x1;	/* H = -B */
+        }
+    } else {
+        /* same sign */
+        x0 -= x1;
+        if (((x0 ^ orgx0) & 0x80) == 0) {
+            /* |x0| > |x1| */
+            x1 += x0;	/* L = A */
+        }
+    }
+    *px0 = (int8_t)x1;
+    *px1 = (int8_t)x0;
+}
+
+/*
+ 1D-Wavelet transform.
+
+ In coefficients array, the famous 'pyramid' decomposition is well used.
+
+ 1D Model:
+   |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
+   |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
+
+ But this method needs line buffer because H/L is different position from X0/X1.
+ So, I used 'interleave' decomposition instead of it.
+
+ 1D Model:
+   |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
+   |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
+
+ In this method, H/L and X0/X1 is always same position.
+ This lead us to more speed and less memory.
+ Of cause, the result of both method is quite same
+ because it's only difference that coefficient position.
+*/
+static inline void wavelet_level(int *data, int size, int l, int skip_pixel)
+{
+    int s, ofs;
+    int8_t *px0;
+    int8_t *end;
+
+    px0 = (int8_t*)data;
+    s = (8 << l) * skip_pixel;
+    end = px0 + (size >> (l + 1)) * s;
+    s -= 2;
+    ofs = (4 << l) * skip_pixel;
+
+    while (px0 < end) {
+        harr(px0, px0 + ofs);
+        px0++;
+        harr(px0, px0 + ofs);
+        px0++;
+        harr(px0, px0 + ofs);
+        px0 += s;
+    }
+}
+
+#ifndef ZYWRLE_QUANTIZE
+/* Type A:lower bit omitting of EZW style. */
+static inline void filter_wavelet_square(int *buf, int width, int height,
+                                         int level, int l)
+{
+    int r, s;
+    int x, y;
+    int *h;
+    const unsigned int *m;
+
+    m = &(zywrle_param[level - 1][l]);
+    s = 2 << l;
+
+    for (r = 1; r < 4; r++) {
+        h = buf;
+        if (r & 0x01) {
+            h += s >> 1;
+        }
+        if (r & 0x02) {
+            h += (s >> 1) * width;
+        }
+        for (y = 0; y < height / s; y++) {
+            for (x = 0; x < width / s; x++) {
+                /*
+                  these are same following code.
+                  h[x] = h[x] / (~m[x]+1) * (~m[x]+1);
+                  ( round h[x] with m[x] bit )
+                  '&' operator isn't 'round' but is 'floor'.
+                  So, we must offset when h[x] is negative.
+                */
+                if (((int8_t*)h)[0] & 0x80) {
+                    ((int8_t*)h)[0] += ~((int8_t*)m)[0];
+                }
+                if (((int8_t*)h)[1] & 0x80) {
+                    ((int8_t*)h)[1] += ~((int8_t*)m)[1];
+                }
+                if (((int8_t*)h)[2] & 0x80) {
+                    ((int8_t*)h)[2] += ~((int8_t*)m)[2];
+                }
+                *h &= *m;
+                h += s;
+            }
+            h += (s-1)*width;
+        }
+    }
+}
+#else
+/*
+ Type B:Non liner quantization filter.
+
+ Coefficients have Gaussian curve and smaller value which is
+ large part of coefficients isn't more important than larger value.
+ So, I use filter of Non liner quantize/dequantize table.
+ In general, Non liner quantize formula is explained as following.
+
+    y=f(x)   = sign(x)*round( ((abs(x)/(2^7))^ r   )* 2^(bo-1) )*2^(8-bo)
+    x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
+ ( r:power coefficient  bi:effective MSB in input  bo:effective MSB in output )
+
+   r < 1.0 : Smaller value is more important than larger value.
+   r > 1.0 : Larger value is more important than smaller value.
+   r = 1.0 : Liner quantization which is same with EZW style.
+
+ r = 0.75 is famous non liner quantization used in MP3 audio codec.
+ In contrast to audio data, larger value is important in wavelet coefficients.
+ So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
+
+ As compared with EZW style liner quantization, this filter tended to be
+ more sharp edge and be more compression rate but be more blocking noise and be
+ less quality. Especially, the surface of graphic objects has distinguishable
+ noise in middle quality mode.
+
+ We need only quantized-dequantized(filtered) value rather than quantized value
+ itself because all values are packed or palette-lized in later ZRLE section.
+ This lead us not to need to modify client decoder when we change
+ the filtering procedure in future.
+ Client only decodes coefficients given by encoder.
+*/
+static inline void filter_wavelet_square(int *buf, int width, int height,
+                                         int level, int l)
+{
+    int r, s;
+    int x, y;
+    int *h;
+    const int8_t **m;
+
+    m = zywrle_param[level - 1][l];
+    s = 2 << l;
+
+    for (r = 1; r < 4; r++) {
+        h = buf;
+        if (r & 0x01) {
+            h += s >> 1;
+        }
+        if (r & 0x02) {
+            h += (s >> 1) * width;
+        }
+        for (y = 0; y < height / s; y++) {
+            for (x = 0; x < width / s; x++) {
+                ((int8_t*)h)[0] = m[0][((uint8_t*)h)[0]];
+                ((int8_t*)h)[1] = m[1][((uint8_t*)h)[1]];
+                ((int8_t*)h)[2] = m[2][((uint8_t*)h)[2]];
+                h += s;
+            }
+            h += (s - 1) * width;
+        }
+    }
+}
+#endif
+
+static inline void wavelet(int *buf, int width, int height, int level)
+{
+	int l, s;
+	int *top;
+	int *end;
+
+	for (l = 0; l < level; l++) {
+		top = buf;
+		end = buf + height * width;
+		s = width << l;
+		while (top < end) {
+			wavelet_level(top, width, l, 1);
+			top += s;
+		}
+		top = buf;
+		end = buf + width;
+		s = 1<<l;
+		while (top < end) {
+			wavelet_level(top, height, l, width);
+			top += s;
+		}
+		filter_wavelet_square(buf, width, height, level, l);
+	}
+}
+
+
+/* Load/Save coefficients stuffs.
+ Coefficients manages as 24 bits little-endian pixel. */
+#define ZYWRLE_LOAD_COEFF(src, r, g, b)         \
+    do {                                        \
+	r = ((int8_t*)src)[2];                  \
+	g = ((int8_t*)src)[1];                  \
+	b = ((int8_t*)src)[0];                  \
+    } while (0)
+
+#define ZYWRLE_SAVE_COEFF(dst, r, g, b)       \
+    do {                                      \
+	((int8_t*)dst)[2] = (int8_t)r;        \
+	((int8_t*)dst)[1] = (int8_t)g;        \
+	((int8_t*)dst)[0] = (int8_t)b;        \
+    } while (0)
+
+/*
+  RGB <=> YUV conversion stuffs.
+  YUV coversion is explained as following formula in strict meaning:
+  Y =  0.299R + 0.587G + 0.114B (   0<=Y<=255)
+  U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
+  V =  0.500R - 0.419G - 0.081B (-128<=V<=127)
+
+  I use simple conversion RCT(reversible color transform) which is described
+  in JPEG-2000 specification.
+  Y = (R + 2G + B)/4 (   0<=Y<=255)
+  U = B-G (-256<=U<=255)
+  V = R-G (-256<=V<=255)
+*/
+
+/* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
+   For make Same N-bit, UV is lossy.
+   More exact PLHarr, we reduce to odd range(-127<=x<=127). */
+#define ZYWRLE_RGBYUV_(r, g, b, y, u, v, ymask, uvmask)          \
+    do {                                                         \
+	y = (r + (g << 1) + b) >> 2;                             \
+	u =  b - g;                                              \
+	v =  r - g;                                              \
+	y -= 128;                                                \
+	u >>= 1;                                                 \
+	v >>= 1;                                                 \
+	y &= ymask;                                              \
+	u &= uvmask;                                             \
+	v &= uvmask;                                             \
+	if (y == -128) {                                         \
+            y += (0xFFFFFFFF - ymask + 1);                       \
+        }                                                        \
+	if (u == -128) {                                         \
+            u += (0xFFFFFFFF - uvmask + 1);                      \
+        }                                                        \
+	if (v == -128) {                                         \
+            v += (0xFFFFFFFF - uvmask + 1);                      \
+        }                                                        \
+    } while (0)
+
+
+/*
+ coefficient packing/unpacking stuffs.
+ Wavelet transform makes 4 sub coefficient image from 1 original image.
+
+ model with pyramid decomposition:
+   +------+------+
+   |      |      |
+   |  L   |  Hx  |
+   |      |      |
+   +------+------+
+   |      |      |
+   |  H   |  Hxy |
+   |      |      |
+   +------+------+
+
+ So, we must transfer each sub images individually in strict meaning.
+ But at least ZRLE meaning, following one decompositon image is same as
+ avobe individual sub image. I use this format.
+ (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
+  for simplified procedure for any wavelet level.)
+
+   +------+------+
+   |      L      |
+   +------+------+
+   |      Hx     |
+   +------+------+
+   |      Hy     |
+   +------+------+
+   |      Hxy    |
+   +------+------+
+*/
+#define ZYWRLE_INC_PTR(data)                         \
+    do {                                             \
+        data++;                                      \
+        if( data - p >= (w + uw) ) {                 \
+            data += scanline-(w + uw);               \
+            p = data;                                \
+        }                                            \
+    } while (0)
+
+#define ZYWRLE_TRANSFER_COEFF(buf, data, t, w, h, scanline, level, TRANS) \
+    do {                                                                \
+        ph = buf;                                                       \
+        s = 2 << level;                                                 \
+        if (t & 0x01) {                                                 \
+            ph += s >> 1;                                               \
+        }                                                               \
+        if (t & 0x02) {                                                 \
+            ph += (s >> 1) * w;                                         \
+        }                                                               \
+        end = ph + h * w;                                               \
+        while (ph < end) {                                              \
+            line = ph + w;                                              \
+            while (ph < line) {                                         \
+                TRANS                                                   \
+                    ZYWRLE_INC_PTR(data);                               \
+                ph += s;                                                \
+            }                                                           \
+            ph += (s - 1) * w;                                          \
+        }                                                               \
+    } while (0)
+
+#define ZYWRLE_PACK_COEFF(buf, data, t, width, height, scanline, level)	\
+    ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \
+                          ZYWRLE_LOAD_COEFF(ph, r, g, b);               \
+                          ZYWRLE_SAVE_PIXEL(data, r, g, b);)
+
+#define ZYWRLE_UNPACK_COEFF(buf, data, t, width, height, scanline, level) \
+    ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \
+                          ZYWRLE_LOAD_PIXEL(data, r, g, b);             \
+                          ZYWRLE_SAVE_COEFF(ph, r, g, b);)
+
+#define ZYWRLE_SAVE_UNALIGN(data, TRANS)                     \
+    do {                                                     \
+        top = buf + w * h;                                   \
+        end = buf + (w + uw) * (h + uh);                     \
+        while (top < end) {                                  \
+            TRANS                                            \
+                ZYWRLE_INC_PTR(data);                        \
+                top++;                                       \
+        }                                                    \
+    } while (0)
+
+#define ZYWRLE_LOAD_UNALIGN(data,TRANS)                                 \
+    do {                                                                \
+        top = buf + w * h;                                              \
+        if (uw) {                                                       \
+            p = data + w;                                               \
+            end = (int*)(p + h * scanline);                             \
+            while (p < (ZRLE_PIXEL*)end) {                              \
+                line = (int*)(p + uw);                                  \
+                while (p < (ZRLE_PIXEL*)line) {                         \
+                    TRANS                                               \
+                        p++;                                            \
+                    top++;                                              \
+                }                                                       \
+                p += scanline - uw;                                     \
+            }                                                           \
+        }                                                               \
+        if (uh) {                                                       \
+            p = data + h * scanline;                                    \
+            end = (int*)(p + uh * scanline);                            \
+            while (p < (ZRLE_PIXEL*)end) {                              \
+                line = (int*)(p + w);                                   \
+                while (p < (ZRLE_PIXEL*)line) {                         \
+                    TRANS                                               \
+                        p++;                                            \
+                    top++;                                              \
+                }                                                       \
+                p += scanline - w;                                      \
+            }                                                           \
+        }                                                               \
+        if (uw && uh) {                                                 \
+            p= data + w + h * scanline;                                 \
+            end = (int*)(p + uh * scanline);                            \
+            while (p < (ZRLE_PIXEL*)end) {                              \
+                line = (int*)(p + uw);                                  \
+                while (p < (ZRLE_PIXEL*)line) {                         \
+                    TRANS                                               \
+                        p++;                                            \
+                    top++;                                              \
+                }                                                       \
+                p += scanline-uw;                                       \
+            }                                                           \
+        }                                                               \
+    } while (0)
+
+static inline void zywrle_calc_size(int *w, int *h, int level)
+{
+    *w &= ~((1 << level) - 1);
+    *h &= ~((1 << level) - 1);
+}
+
+#endif
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index bfe8e86..1d4c5e7 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -172,6 +172,7 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
     local->tight = orig->tight;
     local->zlib = orig->zlib;
     local->hextile = orig->hextile;
+    local->zrle = orig->zrle;
     local->output =  queue->buffer;
     local->csock = -1; /* Don't do any network work on this thread */
 
@@ -183,6 +184,7 @@ static void vnc_async_encoding_end(VncState *orig, VncState *local)
     orig->tight = local->tight;
     orig->zlib = local->zlib;
     orig->hextile = local->hextile;
+    orig->zrle = local->zrle;
     orig->lossy_rect = local->lossy_rect;
 }
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 697b836..9920c0e 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -696,6 +696,12 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
         case VNC_ENCODING_TIGHT_PNG:
             n = vnc_tight_png_send_framebuffer_update(vs, x, y, w, h);
             break;
+        case VNC_ENCODING_ZRLE:
+            n = vnc_zrle_send_framebuffer_update(vs, x, y, w, h);
+            break;
+        case VNC_ENCODING_ZYWRLE:
+            n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h);
+            break;
         default:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
             n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
@@ -1028,6 +1034,7 @@ static void vnc_disconnect_finish(VncState *vs)
 
     vnc_zlib_clear(vs);
     vnc_tight_clear(vs);
+    vnc_zrle_clear(vs);
 
 #ifdef CONFIG_VNC_TLS
     vnc_tls_client_cleanup(vs);
@@ -1766,6 +1773,14 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             vs->features |= VNC_FEATURE_ZLIB_MASK;
             vs->vnc_encoding = enc;
             break;
+        case VNC_ENCODING_ZRLE:
+            vs->features |= VNC_FEATURE_ZRLE_MASK;
+            vs->vnc_encoding = enc;
+            break;
+        case VNC_ENCODING_ZYWRLE:
+            vs->features |= VNC_FEATURE_ZYWRLE_MASK;
+            vs->vnc_encoding = enc;
+            break;
         case VNC_ENCODING_DESKTOPRESIZE:
             vs->features |= VNC_FEATURE_RESIZE_MASK;
             break;
diff --git a/ui/vnc.h b/ui/vnc.h
index 57835f1..706ba3c 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -39,6 +39,8 @@
 #include <stdbool.h>
 
 #include "keymaps.h"
+#include "vnc-palette.h"
+#include "vnc-enc-zrle.h"
 
 // #define _VNC_DEBUG 1
 
@@ -180,6 +182,20 @@ typedef struct VncZlib {
     int level;
 } VncZlib;
 
+typedef struct VncZrle {
+    int type;
+    Buffer fb;
+    Buffer zrle;
+    Buffer tmp;
+    Buffer zlib;
+    z_stream stream;
+    VncPalette palette;
+} VncZrle;
+
+typedef struct VncZywrle {
+    int buf[VNC_ZRLE_TILE_WIDTH * VNC_ZRLE_TILE_HEIGHT];
+} VncZywrle;
+
 #ifdef CONFIG_VNC_THREAD
 struct VncRect
 {
@@ -273,7 +289,8 @@ struct VncState
     VncTight tight;
     VncZlib zlib;
     VncHextile hextile;
-
+    VncZrle zrle;
+    VncZywrle zywrle;
 
     Notifier mouse_mode_notifier;
 
@@ -377,6 +394,8 @@ enum {
 #define VNC_FEATURE_COPYRECT                 6
 #define VNC_FEATURE_RICH_CURSOR              7
 #define VNC_FEATURE_TIGHT_PNG                8
+#define VNC_FEATURE_ZRLE                     9
+#define VNC_FEATURE_ZYWRLE                  10
 
 #define VNC_FEATURE_RESIZE_MASK              (1 << VNC_FEATURE_RESIZE)
 #define VNC_FEATURE_HEXTILE_MASK             (1 << VNC_FEATURE_HEXTILE)
@@ -387,6 +406,8 @@ enum {
 #define VNC_FEATURE_COPYRECT_MASK            (1 << VNC_FEATURE_COPYRECT)
 #define VNC_FEATURE_RICH_CURSOR_MASK         (1 << VNC_FEATURE_RICH_CURSOR)
 #define VNC_FEATURE_TIGHT_PNG_MASK           (1 << VNC_FEATURE_TIGHT_PNG)
+#define VNC_FEATURE_ZRLE_MASK                (1 << VNC_FEATURE_ZRLE)
+#define VNC_FEATURE_ZYWRLE_MASK              (1 << VNC_FEATURE_ZYWRLE)
 
 
 /* Client -> Server message IDs */
@@ -521,4 +542,8 @@ int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y,
                                           int w, int h);
 void vnc_tight_clear(VncState *vs);
 
+int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+void vnc_zrle_clear(VncState *vs);
+
 #endif /* __QEMU_VNC_H */
commit f8562e326bb8bf084b7519a53c6f30627b80ac1e
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:06:00 2011 +0100

    vnc: palette: and fill and color calls.
    
    These two helpers are needed for zrle and zywrle.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c
index f93250b..c478060 100644
--- a/ui/vnc-palette.c
+++ b/ui/vnc-palette.c
@@ -126,3 +126,35 @@ void palette_iter(const VncPalette *palette,
         }
     }
 }
+
+uint32_t palette_color(const VncPalette *palette, int idx, bool *found)
+{
+    int i;
+    VncPaletteEntry *entry;
+
+    for (i = 0; i < VNC_PALETTE_HASH_SIZE; i++) {
+        QLIST_FOREACH(entry, &palette->table[i], next) {
+            if (entry->idx == idx) {
+                *found = true;
+                return entry->color;
+            }
+        }
+    }
+
+    *found = false;
+    return -1;
+}
+
+static void palette_fill_cb(int idx, uint32_t color, void *opaque)
+{
+    uint32_t *colors = opaque;
+
+    colors[idx] = color;
+}
+
+size_t palette_fill(const VncPalette *palette,
+                    uint32_t colors[VNC_PALETTE_MAX_SIZE])
+{
+    palette_iter(palette, palette_fill_cb, colors);
+    return palette_size(palette);
+}
diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h
index c646e4d..3260885 100644
--- a/ui/vnc-palette.h
+++ b/ui/vnc-palette.h
@@ -61,5 +61,8 @@ size_t palette_size(const VncPalette *palette);
 void palette_iter(const VncPalette *palette,
                   void (*iter)(int idx, uint32_t color, void *opaque),
                   void *opaque);
+uint32_t palette_color(const VncPalette *palette, int idx, bool *found);
+size_t palette_fill(const VncPalette *palette,
+                    uint32_t colors[VNC_PALETTE_MAX_SIZE]);
 
 #endif /* VNC_PALETTE_H */
commit 72aefb76f9268bec6eeb60530fd523b60effe610
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:59 2011 +0100

    vnc: palette: add palette_init calls
    
    This allow to use palette on the stack instead of always
    allocating them.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c
index c47420b..f93250b 100644
--- a/ui/vnc-palette.c
+++ b/ui/vnc-palette.c
@@ -56,9 +56,15 @@ VncPalette *palette_new(size_t max, int bpp)
     VncPalette *palette;
 
     palette = qemu_mallocz(sizeof(*palette));
+    palette_init(palette, max, bpp);
+    return palette;
+}
+
+void palette_init(VncPalette *palette, size_t max, int bpp)
+{
+    memset(palette, 0, sizeof (*palette));
     palette->max = max;
     palette->bpp = bpp;
-    return palette;
 }
 
 void palette_destroy(VncPalette *palette)
diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h
index f57d0e7..c646e4d 100644
--- a/ui/vnc-palette.h
+++ b/ui/vnc-palette.h
@@ -51,6 +51,7 @@ typedef struct VncPalette {
 } VncPalette;
 
 VncPalette *palette_new(size_t max, int bpp);
+void palette_init(VncPalette *palette, size_t max, int bpp);
 void palette_destroy(VncPalette *palette);
 
 int palette_put(VncPalette *palette, uint32_t color);
commit e31e3694afef58ba191cbcc6875ec243e5971268
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:58 2011 +0100

    vnc: palette: use a pool to reduce memory allocations
    
    We now that the palette will never have more than 256
    elements. Let's use a pool to reduce malloc calls.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c
index bff6445..c47420b 100644
--- a/ui/vnc-palette.c
+++ b/ui/vnc-palette.c
@@ -63,23 +63,9 @@ VncPalette *palette_new(size_t max, int bpp)
 
 void palette_destroy(VncPalette *palette)
 {
-    int i;
-
     if (palette == NULL) {
-        return ;
+        qemu_free(palette);
     }
-
-    for (i = 0; i < VNC_PALETTE_HASH_SIZE; i++) {
-        VncPaletteEntry *entry = QLIST_FIRST(&palette->table[i]);
-        while (entry) {
-            VncPaletteEntry *tmp = QLIST_NEXT(entry, next);
-            QLIST_REMOVE(entry, next);
-            qemu_free(entry);
-            entry = tmp;
-        }
-    }
-
-    qemu_free(palette);
 }
 
 int palette_put(VncPalette *palette, uint32_t color)
@@ -97,7 +83,7 @@ int palette_put(VncPalette *palette, uint32_t color)
     if (!entry) {
         VncPaletteEntry *entry;
 
-        entry = qemu_mallocz(sizeof(*entry));
+        entry = &palette->pool[palette->size];
         entry->color = color;
         entry->idx = idx;
         QLIST_INSERT_HEAD(&palette->table[hash], entry, next);
diff --git a/ui/vnc-palette.h b/ui/vnc-palette.h
index d0645eb..f57d0e7 100644
--- a/ui/vnc-palette.h
+++ b/ui/vnc-palette.h
@@ -34,6 +34,7 @@
 #include <stdint.h>
 
 #define VNC_PALETTE_HASH_SIZE 256
+#define VNC_PALETTE_MAX_SIZE  256
 
 typedef struct VncPaletteEntry {
     int idx;
@@ -42,7 +43,7 @@ typedef struct VncPaletteEntry {
 } VncPaletteEntry;
 
 typedef struct VncPalette {
-    QObject_HEAD;
+    VncPaletteEntry pool[VNC_PALETTE_MAX_SIZE];
     size_t size;
     size_t max;
     int bpp;
commit ce702e93b0b99562ed42ba5c078914f2209b9a6a
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:57 2011 +0100

    vnc: tight: use the update frequency to choose between lossy and lossless
    
    Use the new update frequency infrastructure to use jpeg for regions with
    high update frequency.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index af45edd..ad9a9a8 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -72,6 +72,26 @@ static const struct {
 static int tight_send_framebuffer_update(VncState *vs, int x, int y,
                                          int w, int h);
 
+#ifdef CONFIG_VNC_JPEG
+static const struct {
+    double jpeg_freq_min;       /* Don't send JPEG if the freq is bellow */
+    double jpeg_freq_threshold; /* Always send JPEG if the freq is above */
+    int jpeg_idx;               /* Allow indexed JPEG */
+    int jpeg_full;              /* Allow full color JPEG */
+} tight_jpeg_conf[] = {
+    { 0,   4,  1, 1 },
+    { 0,   4,  1, 1 },
+    { 0,   4,  1, 1 },
+    { 0,   4,  1, 1 },
+    { 0,   4,  0, 1 },
+    { 0.1, 4,  0, 1 },
+    { 0.2, 4,  0, 1 },
+    { 0.3, 6,  0, 0 },
+    { 0.4, 8,  0, 0 },
+    { 0.5, 10, 0, 0 },
+};
+#endif
+
 #ifdef CONFIG_VNC_PNG
 static const struct {
     int png_zlib_level, png_filters;
@@ -1476,12 +1496,13 @@ static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h,
 #ifdef CONFIG_VNC_JPEG
 static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h,
                               int bg, int fg, int colors,
-                              VncPalette *palette)
+                              VncPalette *palette, bool force)
 {
     int ret;
 
     if (colors == 0) {
-        if (tight_detect_smooth_image(vs, w, h)) {
+        if (force || (tight_jpeg_conf[vs->tight.quality].jpeg_full &&
+                      tight_detect_smooth_image(vs, w, h))) {
             int quality = tight_conf[vs->tight.quality].jpeg_quality;
 
             ret = send_jpeg_rect(vs, x, y, w, h, quality);
@@ -1493,8 +1514,9 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h,
     } else if (colors == 2) {
         ret = send_mono_rect(vs, x, y, w, h, bg, fg);
     } else if (colors <= 256) {
-        if (colors > 96 &&
-            tight_detect_smooth_image(vs, w, h)) {
+        if (force || (colors > 96 &&
+                      tight_jpeg_conf[vs->tight.quality].jpeg_idx &&
+                      tight_detect_smooth_image(vs, w, h))) {
             int quality = tight_conf[vs->tight.quality].jpeg_quality;
 
             ret = send_jpeg_rect(vs, x, y, w, h, quality);
@@ -1514,6 +1536,8 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     uint32_t bg = 0, fg = 0;
     int colors;
     int ret = 0;
+    bool force_jpeg = false;
+    bool allow_jpeg = true;
 
     vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type);
 
@@ -1521,11 +1545,26 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     vnc_raw_send_framebuffer_update(vs, x, y, w, h);
     vnc_tight_stop(vs);
 
+#ifdef CONFIG_VNC_JPEG
+    if (vs->tight.quality != -1) {
+        double freq = vnc_update_freq(vs, x, y, w, h);
+
+        if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) {
+            allow_jpeg = false;
+        }
+        if (freq >= tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) {
+            force_jpeg = true;
+            vnc_sent_lossy_rect(vs, x, y, w, h);
+        }
+    }
+#endif
+
     colors = tight_fill_palette(vs, x, y, w * h, &fg, &bg, &palette);
 
 #ifdef CONFIG_VNC_JPEG
-    if (vs->tight.quality != (uint8_t)-1) {
-        ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, palette);
+    if (allow_jpeg && vs->tight.quality != (uint8_t)-1) {
+        ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, palette,
+                                 force_jpeg);
     } else {
         ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, palette);
     }
@@ -1548,7 +1587,8 @@ static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
     return send_solid_rect(vs);
 }
 
-static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
+static int send_rect_simple(VncState *vs, int x, int y, int w, int h,
+                            bool split)
 {
     int max_size, max_width;
     int max_sub_width, max_sub_height;
@@ -1559,7 +1599,7 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
     max_size = tight_conf[vs->tight.compression].max_rect_size;
     max_width = tight_conf[vs->tight.compression].max_rect_width;
 
-    if (w > max_width || w * h > max_size) {
+    if (split && (w > max_width || w * h > max_size)) {
         max_sub_width = (w > max_width) ? max_width : w;
         max_sub_height = max_size / max_sub_width;
 
@@ -1590,7 +1630,7 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
         /* If a rectangle becomes too large, send its upper part now. */
 
         if (dy - y >= max_rows) {
-            n += send_rect_simple(vs, x, y, w, max_rows);
+            n += send_rect_simple(vs, x, y, w, max_rows, true);
             y += max_rows;
             h -= max_rows;
         }
@@ -1629,7 +1669,7 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
             /* Send rectangles at top and left to solid-color area. */
 
             if (y_best != y) {
-                n += send_rect_simple(vs, x, y, w, y_best-y);
+                n += send_rect_simple(vs, x, y, w, y_best-y, true);
             }
             if (x_best != x) {
                 n += tight_send_framebuffer_update(vs, x, y_best,
@@ -1656,7 +1696,7 @@ static int find_large_solid_color_rect(VncState *vs, int x, int y,
             return n;
         }
     }
-    return n + send_rect_simple(vs, x, y, w, h);
+    return n + send_rect_simple(vs, x, y, w, h, true);
 }
 
 static int tight_send_framebuffer_update(VncState *vs, int x, int y,
@@ -1671,8 +1711,17 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y,
         vs->tight.pixel24 = false;
     }
 
-    if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE)
-        return send_rect_simple(vs, x, y, w, h);
+    if (vs->tight.quality != -1) {
+        double freq = vnc_update_freq(vs, x, y, w, h);
+
+        if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) {
+            return send_rect_simple(vs, x, y, w, h, false);
+        }
+    }
+
+    if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) {
+        return send_rect_simple(vs, x, y, w, h, true);
+    }
 
     /* Calculate maximum number of rows in one non-solid rectangle. */
 
commit 7d964c9d2fc614d2baa788b9e77019b32151f162
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:56 2011 +0100

    vnc: refresh lossy rect after a given timeout
    
    If an adaptive encoding has choosen to send a lossy update
    based on the result of vnc_update_freq(), then it should advertise
    it with vnc_sent_lossy_rect(). This will allow to automatically refresh
    this rect once it's static again.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index 0b5d750..bfe8e86 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -166,6 +166,7 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
     local->features = orig->features;
     local->ds = orig->ds;
     local->vd = orig->vd;
+    local->lossy_rect = orig->lossy_rect;
     local->write_pixels = orig->write_pixels;
     local->clientds = orig->clientds;
     local->tight = orig->tight;
@@ -182,6 +183,7 @@ static void vnc_async_encoding_end(VncState *orig, VncState *local)
     orig->tight = local->tight;
     orig->zlib = local->zlib;
     orig->hextile = local->hextile;
+    orig->lossy_rect = local->lossy_rect;
 }
 
 static int vnc_worker_thread_loop(VncJobQueue *queue)
diff --git a/ui/vnc.c b/ui/vnc.c
index 6eacd1d..697b836 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1014,6 +1014,8 @@ static void vnc_disconnect_start(VncState *vs)
 
 static void vnc_disconnect_finish(VncState *vs)
 {
+    int i;
+
     vnc_jobs_join(vs); /* Wait encoding jobs */
 
     vnc_lock_output(vs);
@@ -1050,6 +1052,10 @@ static void vnc_disconnect_finish(VncState *vs)
 #ifdef CONFIG_VNC_THREAD
     qemu_mutex_destroy(&vs->output_mutex);
 #endif
+    for (i = 0; i < VNC_STAT_ROWS; ++i) {
+        qemu_free(vs->lossy_rect[i]);
+    }
+    qemu_free(vs->lossy_rect);
     qemu_free(vs);
 }
 
@@ -2267,10 +2273,57 @@ static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y)
     return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT];
 }
 
-static void vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
+void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h)
+{
+    int i, j;
+
+    w = (x + w) / VNC_STAT_RECT;
+    h = (y + h) / VNC_STAT_RECT;
+    x /= VNC_STAT_RECT;
+    y /= VNC_STAT_RECT;
+
+    for (j = y; j <= y + h; j++) {
+        for (i = x; i <= x + w; i++) {
+            vs->lossy_rect[j][i] = 1;
+        }
+    }
+}
+
+static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
+{
+    VncState *vs;
+    int sty = y / VNC_STAT_RECT;
+    int stx = x / VNC_STAT_RECT;
+    int has_dirty = 0;
+
+    y = y / VNC_STAT_RECT * VNC_STAT_RECT;
+    x = x / VNC_STAT_RECT * VNC_STAT_RECT;
+
+    QTAILQ_FOREACH(vs, &vd->clients, next) {
+        int j;
+
+        /* kernel send buffers are full -> refresh later */
+        if (vs->output.offset) {
+            continue;
+        }
+
+        if (!vs->lossy_rect[sty][stx]) {
+            continue;
+        }
+        vs->lossy_rect[sty][stx] = 0;
+        for (j = 0; j < VNC_STAT_RECT; ++j) {
+            vnc_set_bits(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
+        }
+        has_dirty++;
+    }
+    return has_dirty;
+}
+
+static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
 {
     int x, y;
     struct timeval res;
+    int has_dirty = 0;
 
     for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
         for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
@@ -2283,7 +2336,7 @@ static void vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
     timersub(tv, &VNC_REFRESH_STATS, &res);
 
     if (timercmp(&vd->guest.last_freq_check, &res, >)) {
-        return ;
+        return has_dirty;
     }
     vd->guest.last_freq_check = *tv;
 
@@ -2302,6 +2355,7 @@ static void vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
 
             if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
                 rect->freq = 0;
+                has_dirty += vnc_refresh_lossy_rect(vd, x, y);
                 memset(rect->times, 0, sizeof (rect->times));
                 continue ;
             }
@@ -2315,6 +2369,7 @@ static void vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
             rect->freq = 1. / rect->freq;
         }
     }
+    return has_dirty;
 }
 
 double vnc_update_freq(VncState *vs, int x, int y, int w, int h)
@@ -2366,7 +2421,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     struct timeval tv;
 
     gettimeofday(&tv, NULL);
-    vnc_update_stats(vd, &tv);
+    has_dirty = vnc_update_stats(vd, &tv);
 
     /*
      * Walk through the guest dirty map.
@@ -2468,7 +2523,13 @@ static void vnc_remove_timer(VncDisplay *vd)
 static void vnc_connect(VncDisplay *vd, int csock)
 {
     VncState *vs = qemu_mallocz(sizeof(VncState));
+    int i;
+
     vs->csock = csock;
+    vs->lossy_rect = qemu_mallocz(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
+    for (i = 0; i < VNC_STAT_ROWS; ++i) {
+        vs->lossy_rect[i] = qemu_mallocz(VNC_STAT_COLS * sizeof (uint8_t));
+    }
 
     VNC_DEBUG("New client on socket %d\n", csock);
     dcl->idle = 0;
diff --git a/ui/vnc.h b/ui/vnc.h
index c0e5ff3..57835f1 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -217,6 +217,8 @@ struct VncState
 
     DisplayState *ds;
     uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in
+                           * vnc-jobs-async.c */
 
     VncDisplay *vd;
     int need_update;
@@ -498,6 +500,7 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
 
 void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
 double vnc_update_freq(VncState *vs, int x, int y, int w, int h);
+void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h);
 
 /* Encodings */
 int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
commit 999342a0fe959dcd549396a255a04d000678e910
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:55 2011 +0100

    vnc: add a way to get the update frequency for a given region
    
    This patch compute the update frequency (in Hz) for each 64x64 rects.
    Any adaptive encoding can get this value using vnc_update_freq(), and
    switch to a lossy encoding if the value is too high.
    
    The frequency is pre-calculated every 500ms, based on the last 10
    updates per 64x64 rect.
    
    If a 64x64 rect was not updated in the last 2 second, then the frequency
    became 0, and all the stored timestamp are reseted.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 9c5c5b3..6eacd1d 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -35,6 +35,8 @@
 #define VNC_REFRESH_INTERVAL_BASE 30
 #define VNC_REFRESH_INTERVAL_INC  50
 #define VNC_REFRESH_INTERVAL_MAX  2000
+static const struct timeval VNC_REFRESH_STATS = { 0, 500000 };
+static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
 
 #include "vnc_keysym.h"
 #include "d3des.h"
@@ -2258,6 +2260,99 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
     return 0;
 }
 
+static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y)
+{
+    struct VncSurface *vs = &vd->guest;
+
+    return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT];
+}
+
+static void vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
+{
+    int x, y;
+    struct timeval res;
+
+    for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
+        for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
+            VncRectStat *rect = vnc_stat_rect(vd, x, y);
+
+            rect->updated = false;
+        }
+    }
+
+    timersub(tv, &VNC_REFRESH_STATS, &res);
+
+    if (timercmp(&vd->guest.last_freq_check, &res, >)) {
+        return ;
+    }
+    vd->guest.last_freq_check = *tv;
+
+    for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
+        for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
+            VncRectStat *rect= vnc_stat_rect(vd, x, y);
+            int count = ARRAY_SIZE(rect->times);
+            struct timeval min, max;
+
+            if (!timerisset(&rect->times[count - 1])) {
+                continue ;
+            }
+
+            max = rect->times[(rect->idx + count - 1) % count];
+            timersub(tv, &max, &res);
+
+            if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
+                rect->freq = 0;
+                memset(rect->times, 0, sizeof (rect->times));
+                continue ;
+            }
+
+            min = rect->times[rect->idx];
+            max = rect->times[(rect->idx + count - 1) % count];
+            timersub(&max, &min, &res);
+
+            rect->freq = res.tv_sec + res.tv_usec / 1000000.;
+            rect->freq /= count;
+            rect->freq = 1. / rect->freq;
+        }
+    }
+}
+
+double vnc_update_freq(VncState *vs, int x, int y, int w, int h)
+{
+    int i, j;
+    double total = 0;
+    int num = 0;
+
+    x =  (x / VNC_STAT_RECT) * VNC_STAT_RECT;
+    y =  (y / VNC_STAT_RECT) * VNC_STAT_RECT;
+
+    for (j = y; j <= y + h; j += VNC_STAT_RECT) {
+        for (i = x; i <= x + w; i += VNC_STAT_RECT) {
+            total += vnc_stat_rect(vs->vd, i, j)->freq;
+            num++;
+        }
+    }
+
+    if (num) {
+        return total / num;
+    } else {
+        return 0;
+    }
+}
+
+static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
+{
+    VncRectStat *rect;
+
+    rect = vnc_stat_rect(vd, x, y);
+    if (rect->updated) {
+        return ;
+    }
+    rect->times[rect->idx] = *tv;
+    rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times);
+    rect->updated = true;
+}
+
 static int vnc_refresh_server_surface(VncDisplay *vd)
 {
     int y;
@@ -2268,6 +2363,11 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     VncState *vs;
     int has_dirty = 0;
 
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    vnc_update_stats(vd, &tv);
+
     /*
      * Walk through the guest dirty map.
      * Check and copy modified bits from guest to server surface.
@@ -2294,6 +2394,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
                 if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
                     continue;
                 memcpy(server_ptr, guest_ptr, cmp_bytes);
+                vnc_rect_updated(vd, x, y, &tv);
                 QTAILQ_FOREACH(vs, &vd->clients, next) {
                     vnc_set_bit(vs->dirty[y], (x / 16));
                 }
diff --git a/ui/vnc.h b/ui/vnc.h
index 4f895be..c0e5ff3 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -80,6 +80,10 @@ typedef void VncSendHextileTile(VncState *vs,
 #define VNC_MAX_HEIGHT 2048
 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
 
+#define VNC_STAT_RECT  64
+#define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT)
+#define VNC_STAT_ROWS (VNC_MAX_HEIGHT / VNC_STAT_RECT)
+
 #define VNC_AUTH_CHALLENGE_SIZE 16
 
 typedef struct VncDisplay VncDisplay;
@@ -92,9 +96,23 @@ typedef struct VncDisplay VncDisplay;
 #include "vnc-auth-sasl.h"
 #endif
 
+struct VncRectStat
+{
+    /* time of last 10 updates, to find update frequency */
+    struct timeval times[10];
+    int idx;
+
+    double freq;        /* Update frequency (in Hz) */
+    bool updated;       /* Already updated during this refresh */
+};
+
+typedef struct VncRectStat VncRectStat;
+
 struct VncSurface
 {
+    struct timeval last_freq_check;
     uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+    VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
     DisplaySurface *ds;
 };
 
@@ -479,6 +497,7 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
                             int32_t encoding);
 
 void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
+double vnc_update_freq(VncState *vs, int x, int y, int w, int h);
 
 /* Encodings */
 int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
commit b31f519e278601225c53519e3b16333d86770ecf
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:54 2011 +0100

    vnc: don't set the quality if lossy encoding are disabled
    
    This should not change the current behavior, but if any new
    encoding try to use the tight quality, it will always be set
    to -1 when lossy encodings are disabled.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 560b98d..9c5c5b3 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1780,7 +1780,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             vs->tight.compression = (enc & 0x0F);
             break;
         case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
-            vs->tight.quality = (enc & 0x0F);
+            if (vs->vd->lossy) {
+                vs->tight.quality = (enc & 0x0F);
+            }
             break;
         default:
             VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
commit 877fdc12b1ac68be256b2a1ee48c3b241c6c92e2
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date:   Mon Feb 21 12:42:20 2011 +0100

    microblaze: Allow targeting little-endian mb
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/configure b/configure
index 791b71d..3036faf 100755
--- a/configure
+++ b/configure
@@ -984,6 +984,7 @@ arm-softmmu \
 cris-softmmu \
 m68k-softmmu \
 microblaze-softmmu \
+microblazeel-softmmu \
 mips-softmmu \
 mipsel-softmmu \
 mips64-softmmu \
@@ -1008,6 +1009,7 @@ armeb-linux-user \
 cris-linux-user \
 m68k-linux-user \
 microblaze-linux-user \
+microblazeel-linux-user \
 mips-linux-user \
 mipsel-linux-user \
 ppc-linux-user \
@@ -3005,7 +3007,8 @@ case "$target_arch2" in
     target_long_alignment=2
     target_llong_alignment=2
   ;;
-  microblaze)
+  microblaze|microblazeel)
+    TARGET_ARCH=microblaze
     bflt="yes"
     target_nptl="yes"
     target_phys_bits=32
@@ -3231,7 +3234,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_M68K_DIS=y"  >> $config_target_mak
     echo "CONFIG_M68K_DIS=y"  >> $libdis_config_mak
   ;;
-  microblaze)
+  microblaze*)
     echo "CONFIG_MICROBLAZE_DIS=y"  >> $config_target_mak
     echo "CONFIG_MICROBLAZE_DIS=y"  >> $libdis_config_mak
   ;;
diff --git a/default-configs/microblazeel-linux-user.mak b/default-configs/microblazeel-linux-user.mak
new file mode 100644
index 0000000..566fdc0
--- /dev/null
+++ b/default-configs/microblazeel-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for microblaze-linux-user
diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak
new file mode 100644
index 0000000..4399b8b
--- /dev/null
+++ b/default-configs/microblazeel-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for microblaze-softmmu
+
+CONFIG_PTIMER=y
+CONFIG_PFLASH_CFI01=y
commit 082e5be809cb8e9806d34abd57e22080bebb598f
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date:   Mon Feb 21 12:30:27 2011 +0100

    pls3adsp1800: Base load_elf endianness on target endianness
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 42de459..6ef4e65 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -167,16 +167,21 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     if (kernel_filename) {
         uint64_t entry, low, high;
         uint32_t base32;
+        int big_endian = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+        big_endian = 1;
+#endif
 
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL,
                                &entry, &low, &high,
-                               1, ELF_MACHINE, 0);
+                               big_endian, ELF_MACHINE, 0);
         base32 = entry;
         if (base32 == 0xc0000000) {
             kernel_size = load_elf(kernel_filename, translate_kernel_address,
                                    NULL, &entry, NULL, NULL,
-                                   1, ELF_MACHINE, 0);
+                                   big_endian, ELF_MACHINE, 0);
         }
         /* Always boot into physical ram.  */
         boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
commit c9f7383c6e5423c1b5111d73346a8314b563f019
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 21 09:51:23 2011 +0100

    do not use qemu_icount_delta in the !use_icount case
    
    The !use_icount code is the same for iothread and non-iothread,
    except that the timeout is different.  Since the timeout might as
    well be infinite and is only masking bugs, use the higher value.
    With this change the !use_icount code is handled equivalently
    in qemu_icount_delta and qemu_calculate_timeout, and we rip it
    out of the former.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index b0db780..88c7b28 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -112,9 +112,7 @@ static int64_t cpu_get_clock(void)
 
 static int64_t qemu_icount_delta(void)
 {
-    if (!use_icount) {
-        return 5000 * (int64_t) 1000000;
-    } else if (use_icount == 1) {
+    if (use_icount == 1) {
         /* When not using an adaptive execution frequency
            we tend to get badly out of sync with real time,
            so just delay for a reasonable amount of time.  */
@@ -1077,43 +1075,36 @@ void quit_timers(void)
 int qemu_calculate_timeout(void)
 {
     int timeout;
+    int64_t add;
+    int64_t delta;
 
-#ifdef CONFIG_IOTHREAD
     /* When using icount, making forward progress with qemu_icount when the
        guest CPU is idle is critical. We only use the static io-thread timeout
        for non icount runs.  */
-    if (!use_icount) {
-        return 1000;
+    if (!use_icount || !vm_running) {
+        return 5000;
     }
-#endif
 
-    if (!vm_running)
-        timeout = 5000;
-    else {
-     /* XXX: use timeout computed from timers */
-        int64_t add;
-        int64_t delta;
-        /* Advance virtual time to the next event.  */
-	delta = qemu_icount_delta();
-        if (delta > 0) {
-            /* If virtual time is ahead of real time then just
-               wait for IO.  */
-            timeout = (delta + 999999) / 1000000;
-        } else {
-            /* Wait for either IO to occur or the next
-               timer event.  */
-            add = qemu_next_deadline();
-            /* We advance the timer before checking for IO.
-               Limit the amount we advance so that early IO
-               activity won't get the guest too far ahead.  */
-            if (add > 10000000)
-                add = 10000000;
-            delta += add;
-            qemu_icount += qemu_icount_round (add);
-            timeout = delta / 1000000;
-            if (timeout < 0)
-                timeout = 0;
-        }
+    /* Advance virtual time to the next event.  */
+    delta = qemu_icount_delta();
+    if (delta > 0) {
+        /* If virtual time is ahead of real time then just
+           wait for IO.  */
+        timeout = (delta + 999999) / 1000000;
+    } else {
+        /* Wait for either IO to occur or the next
+           timer event.  */
+        add = qemu_next_deadline();
+        /* We advance the timer before checking for IO.
+           Limit the amount we advance so that early IO
+           activity won't get the guest too far ahead.  */
+        if (add > 10000000)
+            add = 10000000;
+        delta += add;
+        qemu_icount += qemu_icount_round (add);
+        timeout = delta / 1000000;
+        if (timeout < 0)
+            timeout = 0;
     }
 
     return timeout;
commit 9a31334f419c1d773cf4b4bfbbdace96fbf8a4f4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 14:58:26 2011 +0000

    hw/irq.h: Remove unused SetIRQFunc typedef
    
    Remove the typedef SetIRQFunc, as it is not used by anything.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/irq.h b/hw/irq.h
index 5daae44..f7849ed 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,9 +3,7 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
-/* FIXME: Rmove one of these.  */
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
-typedef void SetIRQFunc(void *opaque, int irq_num, int level);
 
 void qemu_set_irq(qemu_irq irq, int level);
 
commit 81aa06471a5c0ae45537b15f5b44e3f82488cdf5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Feb 21 15:53:05 2011 +0100

    Revert "prep: Disable second IDE channel, as long as ISA IDE emulation doesn't support same irq for both channels"
    
    This reverts commit 491e2a338fdf8310c84f6ebaed1683a871a0700e.

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6c9826b..d86a283 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -690,7 +690,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
     }
 
-    for(i = 0; i < 1/*MAX_IDE_BUS*/; i++) {
+    for(i = 0; i < MAX_IDE_BUS; i++) {
         isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[2 * i],
 		     hd[2 * i + 1]);
commit ee951a37d8873bff7aa58e23222dfd984111b6cb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Feb 19 18:56:22 2011 +0100

    isa-bus: Remove bogus IRQ sharing check
    
    Nothing prevented IRQ sharing on the ISA bus in principle. Not all
    boards supported this, neither each and every card nor driver and OS.
    Still, there existed valid IRQ sharing scenarios, (at least) two of them
    can also be found in QEMU: >2 PC UARTs and the PREP IDE buses.
    
    So remove this artificial restriction from our ISA model.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/hpet.c b/hw/hpet.c
index 82a9a21..91ebb75 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -713,7 +713,6 @@ static int hpet_init(SysBusDevice *dev)
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
 
-    isa_reserve_irq(RTC_ISA_IRQ);
     qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
 
     /* HPET Area */
diff --git a/hw/i8254.c b/hw/i8254.c
index 680caab..eaf5d3e 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -514,7 +514,7 @@ static int pit_initfn(ISADevice *dev)
     s = &pit->channels[0];
     /* the timer 0 is connected to an IRQ */
     s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
-    s->irq = isa_reserve_irq(pit->irq);
+    s->irq = isa_get_irq(pit->irq);
 
     register_ioport_write(pit->iobase, 4, 1, pit_ioport_write, pit);
     register_ioport_read(pit->iobase, 3, 1, pit_ioport_read, pit);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index d4289af..c349644 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -122,7 +122,7 @@ static void pci_piix_init_ports(PCIIDEState *d) {
     for (i = 0; i < 2; i++) {
         ide_bus_new(&d->bus[i], &d->dev.qdev, i);
         ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
-        ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq));
+        ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
 
         bmdma_init(&d->bus[i], &d->bmdma[i]);
         d->bmdma[i].bus = &d->bus[i];
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 0e90679..04f3290 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -145,7 +145,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) {
     for (i = 0; i < 2; i++) {
         ide_bus_new(&d->bus[i], &d->dev.qdev, i);
         ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
-        ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq));
+        ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq));
 
         bmdma_init(&d->bus[i], &d->bmdma[i]);
         d->bmdma[i].bus = &d->bus[i];
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 6f349a5..d07aa41 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -25,7 +25,6 @@
 struct ISABus {
     BusState qbus;
     qemu_irq *irqs;
-    uint32_t assigned;
 };
 static ISABus *isabus;
 target_phys_addr_t isa_mem_base = 0;
@@ -61,33 +60,24 @@ void isa_bus_irqs(qemu_irq *irqs)
 }
 
 /*
- * isa_reserve_irq() reserves the ISA irq and returns the corresponding
- * qemu_irq entry for the i8259.
+ * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
  *
  * This function is only for special cases such as the 'ferr', and
  * temporary use for normal devices until they are converted to qdev.
  */
-qemu_irq isa_reserve_irq(int isairq)
+qemu_irq isa_get_irq(int isairq)
 {
     if (isairq < 0 || isairq > 15) {
         hw_error("isa irq %d invalid", isairq);
     }
-    if (isabus->assigned & (1 << isairq)) {
-        hw_error("isa irq %d already assigned", isairq);
-    }
-    isabus->assigned |= (1 << isairq);
     return isabus->irqs[isairq];
 }
 
 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
 {
     assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
-    if (isabus->assigned & (1 << isairq)) {
-        hw_error("isa irq %d already assigned", isairq);
-    }
-    isabus->assigned |= (1 << isairq);
     dev->isairq[dev->nirqs] = isairq;
-    *p = isabus->irqs[isairq];
+    *p = isa_get_irq(isairq);
     dev->nirqs++;
 }
 
diff --git a/hw/isa.h b/hw/isa.h
index e26abfa..d2b6126 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -26,7 +26,7 @@ struct ISADeviceInfo {
 
 ISABus *isa_bus_new(DeviceState *dev);
 void isa_bus_irqs(qemu_irq *irqs);
-qemu_irq isa_reserve_irq(int isairq);
+qemu_irq isa_get_irq(int isairq);
 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
 void isa_init_ioport(ISADevice *dev, uint16_t ioport);
 void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index ca6c6d7..d8baa6d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -919,7 +919,7 @@ void mips_malta_init (ram_addr_t ram_size,
     isa_bus_irqs(i8259);
     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
-    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9),
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
                           NULL, NULL, 0);
     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
     for (i = 0; i < 8; i++) {
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b4ca9ec..b3ede89 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -113,7 +113,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
     isa_bus_irqs(isa_irq);
 
-    pc_register_ferr_irq(isa_reserve_irq(13));
+    pc_register_ferr_irq(isa_get_irq(13));
 
     pc_vga_init(pci_enabled? pci_bus: NULL);
 
@@ -169,7 +169,7 @@ static void pc_init1(ram_addr_t ram_size,
         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
         /* TODO: Populate SPD eeprom data.  */
         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              isa_reserve_irq(9), *cmos_s3, *smi_irq,
+                              isa_get_irq(9), *cmos_s3, *smi_irq,
                               kvm_enabled());
         for (i = 0; i < 8; i++) {
             DeviceState *eeprom;
commit 7096a96db2d0227598e3c9fb154e53f912a34da8
Author: Roy Tam <roytam at gmail.com>
Date:   Mon Feb 21 08:06:32 2011 +0800

    PS/2 keyboard Scancode Set 3 support
    
    The following patch adds PS/2 keyboard Scancode Set 3 support.
    
    Signed-off-by: Roy Tam <roytam at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ps2.c b/hw/ps2.c
index 762bb00..91b73e0 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -110,14 +110,24 @@ typedef struct {
 
 /* Table to convert from PC scancodes to raw scancodes.  */
 static const unsigned char ps2_raw_keycode[128] = {
-          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
-         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
-         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
-         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
-         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
-        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
-         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
-         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
+  0, 118,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
+ 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  20,  28,  27,
+ 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  93,  26,  34,  33,  42,
+ 50,  49,  58,  65,  73,  74,  89, 124,  17,  41,  88,   5,   6,   4,  12,   3,
+ 11,   2,  10,   1,   9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
+114, 122, 112, 113, 127,  96,  97, 120,   7,  15,  23,  31,  39,  47,  55,  63,
+ 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
+ 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
+};
+static const unsigned char ps2_raw_keycode_set3[128] = {
+  0,   8,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
+ 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  17,  28,  27,
+ 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  92,  26,  34,  33,  42,
+ 50,  49,  58,  65,  73,  74,  89, 126,  25,  41,  20,   7,  15,  23,  31,  39,
+ 47,   2,  63,  71,  79, 118,  95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
+114, 122, 112, 113, 127,  96,  97,  86,  94,  15,  23,  31,  39,  47,  55,  63,
+ 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
+ 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
 };
 
 void ps2_queue(void *opaque, int b)
@@ -143,12 +153,16 @@ static void ps2_put_keycode(void *opaque, int keycode)
 {
     PS2KbdState *s = opaque;
 
-    /* XXX: add support for scancode sets 1 and 3 */
-    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
-      {
-        if (keycode & 0x80)
+    /* XXX: add support for scancode set 1 */
+    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
+        if (keycode & 0x80) {
             ps2_queue(&s->common, 0xf0);
-        keycode = ps2_raw_keycode[keycode & 0x7f];
+        }
+        if (s->scancode_set == 2) {
+            keycode = ps2_raw_keycode[keycode & 0x7f];
+        } else if (s->scancode_set == 3) {
+            keycode = ps2_raw_keycode_set3[keycode & 0x7f];
+        }
       }
     ps2_queue(&s->common, keycode);
 }
commit 92cdfaeb616244581df02ef10ba1ee1bb8d90f70
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 11:05:22 2011 +0000

    target-arm: Fix shift by immediate and narrow where src, dest overlap
    
    For Neon shifts by immediate and narrow, correctly handle the case
    where the source registers and the destination registers overlap
    (the second pass should use the original register contents, not the
    results of the first pass).
    
    This includes a refactoring to pull the size check outside the
    loop rather than inside, since there is now very little common
    code between the size == 3 and size != 3 case.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index fa20e84..dbd958b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4804,64 +4804,68 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
 
                 shift = shift - (1 << (size + 3));
                 size++;
-                switch (size) {
-                case 1:
-                    imm = (uint16_t)shift;
-                    imm |= imm << 16;
-                    tmp2 = tcg_const_i32(imm);
-                    TCGV_UNUSED_I64(tmp64);
-                    break;
-                case 2:
-                    imm = (uint32_t)shift;
-                    tmp2 = tcg_const_i32(imm);
-                    TCGV_UNUSED_I64(tmp64);
-                    break;
-                case 3:
+                if (size == 3) {
                     tmp64 = tcg_const_i64(shift);
-                    TCGV_UNUSED(tmp2);
-                    break;
-                default:
-                    abort();
-                }
-
-                for (pass = 0; pass < 2; pass++) {
-                    if (size == 3) {
-                        neon_load_reg64(cpu_V0, rm + pass);
+                    neon_load_reg64(cpu_V0, rm);
+                    neon_load_reg64(cpu_V1, rm + 1);
+                    for (pass = 0; pass < 2; pass++) {
+                        TCGv_i64 in;
+                        if (pass == 0) {
+                            in = cpu_V0;
+                        } else {
+                            in = cpu_V1;
+                        }
                         if (q) {
                             if (input_unsigned) {
-                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0,
-                                                         tmp64);
+                                gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
                             } else {
-                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0,
-                                                         tmp64);
+                                gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
                             }
                         } else {
                             if (input_unsigned) {
-                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0,
-                                                        tmp64);
+                                gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
                             } else {
-                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0,
-                                                        tmp64);
+                                gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
                             }
                         }
+                        tmp = new_tmp();
+                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
+                        neon_store_reg(rd, pass, tmp);
+                    } /* for pass */
+                    tcg_temp_free_i64(tmp64);
+                } else {
+                    if (size == 1) {
+                        imm = (uint16_t)shift;
+                        imm |= imm << 16;
                     } else {
-                        tmp = neon_load_reg(rm + pass, 0);
+                        /* size == 2 */
+                        imm = (uint32_t)shift;
+                    }
+                    tmp2 = tcg_const_i32(imm);
+                    tmp4 = neon_load_reg(rm + 1, 0);
+                    tmp5 = neon_load_reg(rm + 1, 1);
+                    for (pass = 0; pass < 2; pass++) {
+                        if (pass == 0) {
+                            tmp = neon_load_reg(rm, 0);
+                        } else {
+                            tmp = tmp4;
+                        }
                         gen_neon_shift_narrow(size, tmp, tmp2, q,
                                               input_unsigned);
-                        tmp3 = neon_load_reg(rm + pass, 1);
+                        if (pass == 0) {
+                            tmp3 = neon_load_reg(rm, 1);
+                        } else {
+                            tmp3 = tmp5;
+                        }
                         gen_neon_shift_narrow(size, tmp3, tmp2, q,
                                               input_unsigned);
                         tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
                         dead_tmp(tmp);
                         dead_tmp(tmp3);
-                    }
-                    tmp = new_tmp();
-                    gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
-                    neon_store_reg(rd, pass, tmp);
-                } /* for pass */
-                if (size == 3) {
-                    tcg_temp_free_i64(tmp64);
-                } else {
+                        tmp = new_tmp();
+                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
+                        neon_store_reg(rd, pass, tmp);
+                    } /* for pass */
                     tcg_temp_free_i32(tmp2);
                 }
             } else if (op == 10) {
commit c33171c7f22ba60aad2d011af91d665807b4aced
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 21 11:05:21 2011 +0000

    target-arm: Refactor to pull narrowing decode into separate function
    
    Pull the code which decodes narrowing operations as being either
    signed/unsigned saturate or plain out into its own function.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5f377a4..fa20e84 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4164,6 +4164,23 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
     }
 }
 
+static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
+{
+    if (op) {
+        if (u) {
+            gen_neon_unarrow_sats(size, dest, src);
+        } else {
+            gen_neon_narrow(size, dest, src);
+        }
+    } else {
+        if (u) {
+            gen_neon_narrow_satu(size, dest, src);
+        } else {
+            gen_neon_narrow_sats(size, dest, src);
+        }
+    }
+}
+
 /* Translate a NEON data processing instruction.  Return nonzero if the
    instruction is invalid.
    We process data in a mixture of 32-bit and 64-bit chunks.
@@ -4839,19 +4856,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         dead_tmp(tmp3);
                     }
                     tmp = new_tmp();
-                    if (op == 8) {
-                        if (u) { /* VQSHRUN / VQRSHRUN */
-                            gen_neon_unarrow_sats(size - 1, tmp, cpu_V0);
-                        } else { /* VSHRN / VRSHRN */
-                            gen_neon_narrow(size - 1, tmp, cpu_V0);
-                        }
-                    } else {
-                        if (u) { /* VQSHRN / VQRSHRN */
-                            gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
-                        } else { /* VQSHRN / VQRSHRN */
-                            gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
-                        }
-                    }
+                    gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
                     neon_store_reg(rd, pass, tmp);
                 } /* for pass */
                 if (size == 3) {
@@ -5439,19 +5444,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     for (pass = 0; pass < 2; pass++) {
                         neon_load_reg64(cpu_V0, rm + pass);
                         tmp = new_tmp();
-                        if (op == 36) {
-                            if (q) { /* VQMOVUN */
-                                gen_neon_unarrow_sats(size, tmp, cpu_V0);
-                            } else { /* VMOVN */
-                                gen_neon_narrow(size, tmp, cpu_V0);
-                            }
-                        } else { /* VQMOVN */
-                            if (q) {
-                                gen_neon_narrow_satu(size, tmp, cpu_V0);
-                            } else {
-                                gen_neon_narrow_sats(size, tmp, cpu_V0);
-                            }
-                        }
+                        gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
                         if (pass == 0) {
                             tmp2 = tmp;
                         } else {
commit 57a8821bc6e4457230075a5c8da5f8a083889686
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Feb 4 22:38:48 2011 +0100

    w32: Remove implementation of function ffs
    
    This implementation is no longer needed.
    
    ffs is either a built-in function (for compilations with optimisation)
    or taken from libiberty.a (which was added by the previous patch).
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/oslib-win32.c b/oslib-win32.c
index ab29eae..5f0759f 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -93,13 +93,6 @@ void qemu_set_cloexec(int fd)
 {
 }
 
-/* mingw32 needs ffs for compilations without optimization. */
-int ffs(int i)
-{
-    /* Use gcc's builtin ffs. */
-    return __builtin_ffs(i);
-}
-
 /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
 #define _W32_FT_OFFSET (116444736000000000ULL)
 
commit 08f3896a072c6d05e36ec3fa4fd303ea550ee38f
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Feb 4 22:38:47 2011 +0100

    w32: Use additional library libiberty.a
    
    libiberty.a is part of MinGW and provides useful functions
    like ffs (MinGW) and getopt (MinGW-w64).
    
    It is needed for w64 compilations and allows simpler code for w32.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index e3cecca..791b71d 100755
--- a/configure
+++ b/configure
@@ -474,7 +474,7 @@ if test "$mingw32" = "yes" ; then
   QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
   # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
   QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
-  LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
+  LIBS="-lwinmm -lws2_32 -liberty -liphlpapi $LIBS"
   prefix="c:/Program Files/Qemu"
   mandir="\${prefix}"
   datadir="\${prefix}"
commit 9dda2465472d2252c7172549606f246ec6823592
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Sun Feb 20 21:23:59 2011 +0200

    Fix obvious mistake in pxa2xx i2s driver
    
    RST bit is (1 << 4) bit, not (1 << 3), fix condition
    that enables i2s if ENB is set and RST is not set.
    
    Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9ebbce6..dc595f3 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1661,7 +1661,7 @@ static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr,
         }
         if (value & (1 << 4))				/* EFWR */
             printf("%s: Attempt to use special function\n", __FUNCTION__);
-        s->enable = ((value ^ 4) & 5) == 5;		/* ENB && !RST*/
+        s->enable = (value & 9) == 1;			/* ENB && !RST*/
         pxa2xx_i2s_update(s);
         break;
     case SACR1:
commit 582798b5c6c3ae0e53f099dc516a025b9d8589fd
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Tue Feb 15 15:27:29 2011 +0200

    pxa2xx_keypad: Handle 0xe0xx keycodes
    
    Add handling of 0xe0xx keycodes to pxa2xx_driver.
    Extended keycodes in keymap should be marked with most significant
    bit set (i.e. 0x80). Without this patch it's not possible to handle
    i.e. cursor keys.
    
    Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 5b8890b..d77dbf1 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -83,6 +83,7 @@ struct PXA2xxKeyPadState {
     qemu_irq    irq;
     struct  keymap *map;
     int         pressed_cnt;
+    int         alt_code;
 
     uint32_t    kpc;
     uint32_t    kpdk;
@@ -116,6 +117,11 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
     int row, col, rel, assert_irq = 0;
     uint32_t val;
 
+    if (keycode == 0xe0) {
+        kp->alt_code = 1;
+        return;
+    }
+
     if(!(kp->kpc & KPC_ME)) /* skip if not enabled */
         return;
 
@@ -125,6 +131,10 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
 
         rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */
         keycode &= ~(0x80); /* strip qemu key release bit */
+        if (kp->alt_code) {
+            keycode |= 0x80;
+            kp->alt_code = 0;
+        }
 
         row = kp->map[keycode].row;
         col = kp->map[keycode].column;
commit b976b4c0e7b77082b8dc43bf408dc92efedc53a0
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Tue Feb 15 15:27:28 2011 +0200

    pxa2xx_keypad: enhance emulation of KPAS, KPASMKP regs
    
    Add emulation of KPAS register and proper emulation of
    KPASMKP regs, so now driver supports multipresses and properly
    works with Linux driver.
    
    Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 4c99917..5b8890b 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -82,22 +82,39 @@
 struct PXA2xxKeyPadState {
     qemu_irq    irq;
     struct  keymap *map;
+    int         pressed_cnt;
 
     uint32_t    kpc;
     uint32_t    kpdk;
     uint32_t    kprec;
     uint32_t    kpmk;
     uint32_t    kpas;
-    uint32_t    kpasmkp0;
-    uint32_t    kpasmkp1;
-    uint32_t    kpasmkp2;
-    uint32_t    kpasmkp3;
+    uint32_t    kpasmkp[4];
     uint32_t    kpkdi;
 };
 
+static void pxa27x_keypad_find_pressed_key(PXA2xxKeyPadState *kp, int *row, int *col)
+{
+    int i;
+    for (i = 0; i < 4; i++)
+    {
+        *col = i * 2;
+        for (*row = 0; *row < 8; (*row)++) {
+            if (kp->kpasmkp[i] & (1 << *row))
+                return;
+        }
+        *col = i * 2 + 1;
+        for (*row = 0; *row < 8; (*row)++) {
+            if (kp->kpasmkp[i] & (1 << (*row + 16)))
+                return;
+        }
+    }
+}
+
 static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
 {
-    int row, col,rel;
+    int row, col, rel, assert_irq = 0;
+    uint32_t val;
 
     if(!(kp->kpc & KPC_ME)) /* skip if not enabled */
         return;
@@ -108,46 +125,39 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
 
         rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */
         keycode &= ~(0x80); /* strip qemu key release bit */
+
         row = kp->map[keycode].row;
         col = kp->map[keycode].column;
         if(row == -1 || col == -1)
             return;
-        switch (col) {
-        case 0:
-        case 1:
-            if(rel)
-                kp->kpasmkp0 = ~(0xffffffff);
-            else
-                kp->kpasmkp0 |= KPASMKPx_MKC(row,col);
-            break;
-        case 2:
-        case 3:
-            if(rel)
-                kp->kpasmkp1 = ~(0xffffffff);
-            else
-                kp->kpasmkp1 |= KPASMKPx_MKC(row,col);
-            break;
-        case 4:
-        case 5:
-            if(rel)
-                kp->kpasmkp2 = ~(0xffffffff);
-            else
-                kp->kpasmkp2 |= KPASMKPx_MKC(row,col);
-            break;
-        case 6:
-        case 7:
-            if(rel)
-                kp->kpasmkp3 = ~(0xffffffff);
-            else
-                kp->kpasmkp3 |= KPASMKPx_MKC(row,col);
-            break;
-        } /* switch */
+
+        val = KPASMKPx_MKC(row, col);
+        if (rel) {
+            if (kp->kpasmkp[col / 2] & val) {
+                kp->kpasmkp[col / 2] &= ~val;
+                kp->pressed_cnt--;
+                assert_irq = 1;
+            }
+        } else {
+            if (!(kp->kpasmkp[col / 2] & val)) {
+                kp->kpasmkp[col / 2] |= val;
+                kp->pressed_cnt++;
+                assert_irq = 1;
+            }
+        }
+        kp->kpas = ((kp->pressed_cnt & 0x1f) << 26) | (0xf << 4) | 0xf;
+        if (kp->pressed_cnt == 1) {
+            kp->kpas &= ~((0xf << 4) | 0xf);
+            if (rel)
+                pxa27x_keypad_find_pressed_key(kp, &row, &col);
+            kp->kpas |= ((row & 0xf) << 4) | (col & 0xf);
+        }
         goto out;
     }
     return;
 
 out:
-    if(kp->kpc & KPC_MIE) {
+    if (assert_irq && (kp->kpc & KPC_MIE)) {
         kp->kpc |= KPC_MI;
         qemu_irq_raise(kp->irq);
     }
@@ -194,16 +204,16 @@ static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
         return s->kpas;
         break;
     case KPASMKP0:
-        return s->kpasmkp0;
+        return s->kpasmkp[0];
         break;
     case KPASMKP1:
-        return s->kpasmkp1;
+        return s->kpasmkp[1];
         break;
     case KPASMKP2:
-        return s->kpasmkp2;
+        return s->kpasmkp[2];
         break;
     case KPASMKP3:
-        return s->kpasmkp3;
+        return s->kpasmkp[3];
         break;
     case KPKDI:
         return s->kpkdi;
@@ -237,16 +247,16 @@ static void pxa2xx_keypad_write(void *opaque,
         s->kpas = value;
         break;
     case KPASMKP0:
-        s->kpasmkp0 = value;
+        s->kpasmkp[0] = value;
         break;
     case KPASMKP1:
-        s->kpasmkp1 = value;
+        s->kpasmkp[1] = value;
         break;
     case KPASMKP2:
-        s->kpasmkp2 = value;
+        s->kpasmkp[2] = value;
         break;
     case KPASMKP3:
-        s->kpasmkp3 = value;
+        s->kpasmkp[3] = value;
         break;
     case KPKDI:
         s->kpkdi = value;
@@ -278,10 +288,10 @@ static void pxa2xx_keypad_save(QEMUFile *f, void *opaque)
     qemu_put_be32s(f, &s->kprec);
     qemu_put_be32s(f, &s->kpmk);
     qemu_put_be32s(f, &s->kpas);
-    qemu_put_be32s(f, &s->kpasmkp0);
-    qemu_put_be32s(f, &s->kpasmkp1);
-    qemu_put_be32s(f, &s->kpasmkp2);
-    qemu_put_be32s(f, &s->kpasmkp3);
+    qemu_put_be32s(f, &s->kpasmkp[0]);
+    qemu_put_be32s(f, &s->kpasmkp[1]);
+    qemu_put_be32s(f, &s->kpasmkp[2]);
+    qemu_put_be32s(f, &s->kpasmkp[3]);
     qemu_put_be32s(f, &s->kpkdi);
 
 }
@@ -295,10 +305,10 @@ static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be32s(f, &s->kprec);
     qemu_get_be32s(f, &s->kpmk);
     qemu_get_be32s(f, &s->kpas);
-    qemu_get_be32s(f, &s->kpasmkp0);
-    qemu_get_be32s(f, &s->kpasmkp1);
-    qemu_get_be32s(f, &s->kpasmkp2);
-    qemu_get_be32s(f, &s->kpasmkp3);
+    qemu_get_be32s(f, &s->kpasmkp[0]);
+    qemu_get_be32s(f, &s->kpasmkp[1]);
+    qemu_get_be32s(f, &s->kpasmkp[2]);
+    qemu_get_be32s(f, &s->kpasmkp[3]);
     qemu_get_be32s(f, &s->kpkdi);
 
     return 0;
commit 5a5e3d55ffbcb81f97b4a6353f1649b1b9772938
Author: David 'Digit' Turner <digit at google.com>
Date:   Mon Jan 10 23:11:40 2011 +0100

    qdev: Fix printout of bit device properties with bit index >= 8
    
    Signed-off-by: David 'Digit' Turner <digit at google.com>
    Acked-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index a493087..a45b61e 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -51,7 +51,7 @@ static int parse_bit(DeviceState *dev, Property *prop, const char *str)
 
 static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
 {
-    uint8_t *p = qdev_get_prop_ptr(dev, prop);
+    uint32_t *p = qdev_get_prop_ptr(dev, prop);
     return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
 }
 
commit 7464f0587b2938a3e10e9f995f384df8a5f298ac
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Jan 21 22:50:30 2011 +0100

    check-qdict: Fix possible crash
    
    This warning is reported by cppcheck:
    
    check-qdict.c:270: warning: scanf without field width limits can crash with huge input data
    
    Fix it by limiting the field widths to 127 (both key and value take
    127 characters + a terminating '\0' byte).
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/check-qdict.c b/check-qdict.c
index 6afce5a..ecc7fd7 100644
--- a/check-qdict.c
+++ b/check-qdict.c
@@ -267,8 +267,9 @@ static QString *read_line(FILE *file, char *key)
 {
     char value[128];
 
-    if (fscanf(file, "%s%s", key, value) == EOF)
+    if (fscanf(file, "%127s%127s", key, value) == EOF) {
         return NULL;
+    }
     remove_dots(key);
     return qstring_from_str(value);
 }
commit 8da91fffeaffba5f014dfdcc88b672590e83b7fc
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Jan 21 22:49:29 2011 +0100

    tests: Fix two memory leaks
    
    Although both leaks are not really important, fix them
    to avoid cppcheck warnings:
    
    tests/linux-test.c:433: error: Memory leak: stack1
    tests/linux-test.c:433: error: Memory leak: stack2
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tests/linux-test.c b/tests/linux-test.c
index 9986e29..2e4a746 100644
--- a/tests/linux-test.c
+++ b/tests/linux-test.c
@@ -426,7 +426,9 @@ void test_clone(void)
                            CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
 
     while (waitpid(pid1, &status1, 0) != pid1);
+    free(stack1);
     while (waitpid(pid2, &status2, 0) != pid2);
+    free(stack2);
     if (thread1_res != 5 ||
         thread2_res != 6)
         error("clone");
commit 1bbd185fa826a2da7c6089b968f9f7d08438c2c8
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Jan 22 13:07:26 2011 +0000

    qemu-char: Check for missing backend name
    
    Check if the backend option is missing before searching the backend
    table.  This fixes a NULL pointer dereference when QEMU is invoked with
    the following invalid command-line:
    
      $ qemu -chardev id=foo,path=/tmp/socket
    
    Previously QEMU would segfault, now it produces this error message:
    
      chardev: "foo" missing backend
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/qemu-char.c b/qemu-char.c
index ee4f4ca..bd4e944 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2506,6 +2506,11 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
         return NULL;
     }
 
+    if (qemu_opt_get(opts, "backend") == NULL) {
+        fprintf(stderr, "chardev: \"%s\" missing backend\n",
+                qemu_opts_id(opts));
+        return NULL;
+    }
     for (i = 0; i < ARRAY_SIZE(backend_table); i++) {
         if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0)
             break;
commit 9f953ca0b8ae71f4ea8112a3aac36454a2c4b907
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Jan 22 13:02:46 2011 +0100

    s390: Fix memory leak
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index f29b624..850422f 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -204,6 +204,7 @@ static void s390_init(ram_addr_t ram_size,
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         bios_size = load_image(bios_filename, qemu_get_ram_ptr(ZIPL_LOAD_ADDR));
+        qemu_free(bios_filename);
 
         if ((long)bios_size < 0) {
             hw_error("could not load bootloader '%s'\n", bios_name);
commit e98ccb3fbba94d0b2165caabf7aeee370d4ce900
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Jan 22 13:02:45 2011 +0100

    ppc405: Fix memory leak
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Acked-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 9abede7..ad27181 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -560,6 +560,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset));
+            qemu_free(filename);
         } else {
             bios_size = -1;
         }
commit 386bbf45720b00496d5b9f9137359801c4e7ac0e
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Jan 22 13:02:44 2011 +0100

    pci: Fix memory leak
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pci.c b/hw/pci.c
index 5e6e216..8b76cea 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1875,6 +1875,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     if (size < 0) {
         error_report("%s: failed to find romfile \"%s\"",
                      __FUNCTION__, pdev->romfile);
+        qemu_free(path);
         return -1;
     }
     if (size & (size - 1)) {
commit 3299369856db73a02c68869cb03fd1e24238eb9b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Feb 9 18:45:09 2011 +0200

    vhost: disable on tap link down
    
    qemu makes it possible to disable link at tap which is not communicated
    to the guest but causes all packets to be dropped.
    
    When vhost-net is enabled, vhost needs to be aware of both the virtio
    link_down and the peer link_down. we switch to userspace emulation when
    either is down.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reported-by: pradeep <psuriset at linux.vnet.ibm.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 671d952..20cf680 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -115,7 +115,8 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
     if (!tap_get_vhost_net(n->nic->nc.peer)) {
         return;
     }
-    if (!!n->vhost_started == virtio_net_started(n, status)) {
+    if (!!n->vhost_started == virtio_net_started(n, status) &&
+                              !n->nic->nc.peer->link_down) {
         return;
     }
     if (!n->vhost_started) {
commit ab1cbe1c6df3c1f11db42148f929113ad9608ba1
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Feb 9 18:45:04 2011 +0200

    net: notify peer about link status change
    
    qemu makes it possible to disable link at tap which is not communicated
    to the guest but causes all packets to be dropped.
    
    This works for virtio userspace, as qemu stops giving it packets, but
    not for virtio-net connected to vhost-net as that does not get notified
    about this change.
    
    Notify peer when this happens, which will then be used by the follow-up
    patch to stop/start vhost-net.
    
    Note: it might be a good idea to make peer link status match tap in this
    case, so the guest gets an event and updates the carrier state. For now
    stay bug for bug compatible with what we used to have in userspace.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reported-by: pradeep <psuriset at linux.vnet.ibm.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/net.c b/net.c
index 9ba5be2..ec4745d 100644
--- a/net.c
+++ b/net.c
@@ -1324,6 +1324,17 @@ done:
     if (vc->info->link_status_changed) {
         vc->info->link_status_changed(vc);
     }
+
+    /* Notify peer. Don't update peer link status: this makes it possible to
+     * disconnect from host network without notifying the guest.
+     * FIXME: is disconnected link status change operation useful?
+     *
+     * Current behaviour is compatible with qemu vlans where there could be
+     * multiple clients that can still communicate with each other in
+     * disconnected mode. For now maintain this compatibility. */
+    if (vc->peer && vc->peer->info->link_status_changed) {
+        vc->peer->info->link_status_changed(vc->peer);
+    }
     return 0;
 }
 
commit f45a11088b9971470218e156f8c78a5fce33adb5
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Feb 5 20:59:49 2011 +0100

    w32: Fix arguments for GetProcessAffinityMask, SetProcessAffinityMask
    
    These functions take arguments of type PDWORD_PTR which is a
    pointer to a DWORD_PTR, not a pointer to a DWORD.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/os-win32.c b/os-win32.c
index 566d5e9..b214e6a 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -180,7 +180,7 @@ void os_setup_early_signal_handling(void)
     /* Note: cpu_interrupt() is currently not SMP safe, so we force
        QEMU to run on a single CPU */
     HANDLE h;
-    DWORD mask, smask;
+    DWORD_PTR mask, smask;
     int i;
 
     SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
commit 33ebc29337face0f030719960338af3d2654cdf8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 15 13:44:49 2011 +0000

    target-arm: Fix unsigned VQRSHL by large shift counts
    
    Correctly handle VQRSHL of unsigned values by a shift count of the
    width of the data type or larger, which must be special-cased in the
    qrshl_u* helper functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 1b41d46..002a9c1 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -818,7 +818,18 @@ uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
 #define NEON_FN(dest, src1, src2) do { \
     int8_t tmp; \
     tmp = (int8_t)src2; \
-    if (tmp < 0) { \
+    if (tmp >= (ssize_t)sizeof(src1) * 8) { \
+        if (src1) { \
+            SET_QC(); \
+            dest = ~0; \
+        } else { \
+            dest = 0; \
+        } \
+    } else if (tmp < -(ssize_t)sizeof(src1) * 8) { \
+        dest = 0; \
+    } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \
+        dest = src1 >> (sizeof(src1) * 8 - 1); \
+    } else if (tmp < 0) { \
         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
     } else { \
         dest = src1 << tmp; \
@@ -837,7 +848,18 @@ uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
 {
     uint32_t dest;
     int8_t shift = (int8_t)shiftop;
-    if (shift < 0) {
+    if (shift >= 32) {
+        if (val) {
+            SET_QC();
+            dest = ~0;
+        } else {
+            dest = 0;
+        }
+    } else if (shift < -32) {
+        dest = 0;
+    } else if (shift == -32) {
+        dest = val >> 31;
+    } else if (shift < 0) {
         uint64_t big_dest = ((uint64_t)val + (1 << (-1 - shift)));
         dest = big_dest >> -shift;
     } else {
@@ -855,7 +877,16 @@ uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
 uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
-    if (shift < 0) {
+    if (shift >= 64) {
+        if (val) {
+            SET_QC();
+            val = ~0;
+        }
+    } else if (shift < -64) {
+        val = 0;
+    } else if (shift == -64) {
+        val >>= 63;
+    } else if (shift < 0) {
         val >>= (-shift - 1);
         if (val == UINT64_MAX) {
             /* In this case, it means that the rounding constant is 1,
commit 7b6ecf5b3a1605dfa6f3e3df3d8e42e9db9fcc71
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 15 13:44:48 2011 +0000

    target-arm: Fix signed VQRSHL by large shift counts
    
    Handle the case of signed VQRSHL by a shift count of the width of the
    data type or larger, which must be special cased in the qrshl_s*
    helper functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 235a32c..1b41d46 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -880,7 +880,19 @@ uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
 #define NEON_FN(dest, src1, src2) do { \
     int8_t tmp; \
     tmp = (int8_t)src2; \
-    if (tmp < 0) { \
+    if (tmp >= (ssize_t)sizeof(src1) * 8) { \
+        if (src1) { \
+            SET_QC(); \
+            dest = (1 << (sizeof(src1) * 8 - 1)); \
+            if (src1 > 0) { \
+                dest--; \
+            } \
+        } else { \
+            dest = 0; \
+        } \
+    } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
+        dest = 0; \
+    } else if (tmp < 0) { \
         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
     } else { \
         dest = src1 << tmp; \
@@ -903,7 +915,16 @@ uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
     int32_t dest;
     int32_t val = (int32_t)valop;
     int8_t shift = (int8_t)shiftop;
-    if (shift < 0) {
+    if (shift >= 32) {
+        if (val) {
+            SET_QC();
+            dest = (val >> 31) ^ ~SIGNBIT;
+        } else {
+            dest = 0;
+        }
+    } else if (shift <= -32) {
+        dest = 0;
+    } else if (shift < 0) {
         int64_t big_dest = ((int64_t)val + (1 << (-1 - shift)));
         dest = big_dest >> -shift;
     } else {
@@ -923,7 +944,14 @@ uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
 
-    if (shift < 0) {
+    if (shift >= 64) {
+        if (val) {
+            SET_QC();
+            val = (val >> 63) ^ ~SIGNBIT64;
+        }
+    } else if (shift <= -64) {
+        val = 0;
+    } else if (shift < 0) {
         val >>= (-shift - 1);
         if (val == INT64_MAX) {
             /* In this case, it means that the rounding constant is 1,
commit 0b36f4cd4707d91389aad64f96d00a705645ddc9
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 15 13:44:47 2011 +0000

    target-arm: fix decoding of Neon 64 bit shifts.
    
    Fix decoding of 64 bits variants of VSHRN, VRSHRN, VQSHRN, VQSHRUN,
    VQRSHRN, VQRSHRUN, taking into account whether inputs are unsigned
    or not.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index e8e6b42..5f377a4 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4783,6 +4783,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             } else if (op < 10) {
                 /* Shift by immediate and narrow:
                    VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
+                int input_unsigned = (op == 8) ? !u : u;
+
                 shift = shift - (1 << (size + 3));
                 size++;
                 switch (size) {
@@ -4809,33 +4811,46 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     if (size == 3) {
                         neon_load_reg64(cpu_V0, rm + pass);
                         if (q) {
-                          if (u)
-                            gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
-                          else
-                            gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
+                            if (input_unsigned) {
+                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0,
+                                                         tmp64);
+                            } else {
+                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0,
+                                                         tmp64);
+                            }
                         } else {
-                          if (u)
-                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
-                          else
-                            gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
+                            if (input_unsigned) {
+                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0,
+                                                        tmp64);
+                            } else {
+                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0,
+                                                        tmp64);
+                            }
                         }
                     } else {
                         tmp = neon_load_reg(rm + pass, 0);
-                        gen_neon_shift_narrow(size, tmp, tmp2, q, u);
+                        gen_neon_shift_narrow(size, tmp, tmp2, q,
+                                              input_unsigned);
                         tmp3 = neon_load_reg(rm + pass, 1);
-                        gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
+                        gen_neon_shift_narrow(size, tmp3, tmp2, q,
+                                              input_unsigned);
                         tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
                         dead_tmp(tmp);
                         dead_tmp(tmp3);
                     }
                     tmp = new_tmp();
-                    if (op == 8 && !u) {
-                        gen_neon_narrow(size - 1, tmp, cpu_V0);
+                    if (op == 8) {
+                        if (u) { /* VQSHRUN / VQRSHRUN */
+                            gen_neon_unarrow_sats(size - 1, tmp, cpu_V0);
+                        } else { /* VSHRN / VRSHRN */
+                            gen_neon_narrow(size - 1, tmp, cpu_V0);
+                        }
                     } else {
-                        if (op == 8)
-                            gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
-                        else
+                        if (u) { /* VQSHRN / VQRSHRN */
                             gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
+                        } else { /* VQSHRN / VQRSHRN */
+                            gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
+                        }
                     }
                     neon_store_reg(rd, pass, tmp);
                 } /* for pass */
commit b408a9b072fdc3d9b1d732ec7bddce52b2030315
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 15 13:44:46 2011 +0000

    target-arm: fix Neon VQSHRN and VSHRN.
    
    Call the normal shift helpers instead of the rounding ones.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 16d2ebf..e8e6b42 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4063,8 +4063,8 @@ static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
     } else {
         if (u) {
             switch (size) {
-            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
-            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
+            case 1: gen_helper_neon_shl_u16(var, var, shift); break;
+            case 2: gen_helper_neon_shl_u32(var, var, shift); break;
             default: abort();
             }
         } else {
commit 960e623bfd45c92ce165177b8a0e748867fe5878
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 15 13:44:45 2011 +0000

    target-arm: Fix saturated values for Neon right shifts
    
    Fix value returned by signed 8 and 16 bit qrshl helpers
    when the result has saturated.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index c97aa7d..235a32c 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -886,7 +886,10 @@ uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
         dest = src1 << tmp; \
         if ((dest >> tmp) != src1) { \
             SET_QC(); \
-            dest = src1 >> 31; \
+            dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
+            if (src1 > 0) { \
+                dest--; \
+            } \
         } \
     }} while (0)
 NEON_VOP_ENV(qrshl_s8, neon_s8, 4)
commit 51e3930fc7ae8d3cff1ff0ecfdd63403b4c20f36
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 15 13:44:44 2011 +0000

    target-arm: fix unsigned 64 bit right shifts.
    
    Fix range of shift amounts which always give 0 as result.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 52ef994..c97aa7d 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -639,7 +639,7 @@ uint32_t HELPER(neon_rshl_u32)(uint32_t val, uint32_t shiftop)
 uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
-    if (shift >= 64 || shift < 64) {
+    if (shift >= 64 || shift < -64) {
         val = 0;
     } else if (shift == -64) {
         /* Rounding a 1-bit result just preserves that bit.  */
commit b6c63b9891f0b1415f96e027d5dc8a430c7ec153
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 15 13:44:43 2011 +0000

    target-arm: Fix unsigned VRSHL.s8 and .s16 right shifts by type width
    
    Fix handling of unsigned VRSHL.s8 and .s16 right shifts by the type
    width.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 0ddfe6d..52ef994 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -605,7 +605,7 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
         tmp < -(ssize_t)sizeof(src1) * 8) { \
         dest = 0; \
     } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \
-        dest = src1 >> (tmp - 1); \
+        dest = src1 >> (-tmp - 1); \
     } else if (tmp < 0) { \
         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
     } else { \
commit 0670a7b65b0ce122c9f415ac7ae78e015a52a30a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 15 13:44:42 2011 +0000

    target-arm: Fix signed VRSHL by large shift counts
    
    Correctly handle VRSHL of signed values by a shift count of the
    width of the data type or larger, which must be special-cased in the
    rshl_s* helper functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index a32a2c8..0ddfe6d 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -543,14 +543,9 @@ uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
 #define NEON_FN(dest, src1, src2) do { \
     int8_t tmp; \
     tmp = (int8_t)src2; \
-    if (tmp >= (ssize_t)sizeof(src1) * 8) { \
+    if ((tmp >= (ssize_t)sizeof(src1) * 8) \
+        || (tmp <= -(ssize_t)sizeof(src1) * 8)) { \
         dest = 0; \
-    } else if (tmp < -(ssize_t)sizeof(src1) * 8) { \
-        dest = src1 >> (sizeof(src1) * 8 - 1); \
-    } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \
-        dest = src1 >> (tmp - 1); \
-        dest++; \
-        dest >>= 1; \
     } else if (tmp < 0) { \
         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
     } else { \
@@ -584,14 +579,8 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     int64_t val = valop;
-    if (shift >= 64) {
+    if ((shift >= 64) || (shift <= -64)) {
         val = 0;
-    } else if (shift < -64) {
-        val >>= 63;
-    } else if (shift == -63) {
-        val >>= 63;
-        val++;
-        val >>= 1;
     } else if (shift < 0) {
         val >>= (-shift - 1);
         if (val == INT64_MAX) {
commit 4bd4ee072cfbd3555b34279c8529f7f5f8d6c14a
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 15 13:44:41 2011 +0000

    target-arm: Fix rounding constant addition for Neon shifts
    
    Handle cases where adding the rounding constant could overflow in Neon
    shift instructions: VRSHR, VRSRA, VQRSHRN, VQRSHRUN, VRSHRN.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    [peter.maydell at linaro.org: fix handling of large shifts in rshl_s32,
    calculate signed saturated value as other functions do.]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index bcc1b4b..a32a2c8 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -558,9 +558,28 @@ uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
     }} while (0)
 NEON_VOP(rshl_s8, neon_s8, 4)
 NEON_VOP(rshl_s16, neon_s16, 2)
-NEON_VOP(rshl_s32, neon_s32, 1)
 #undef NEON_FN
 
+/* The addition of the rounding constant may overflow, so we use an
+ * intermediate 64 bits accumulator.  */
+uint32_t HELPER(neon_rshl_s32)(uint32_t valop, uint32_t shiftop)
+{
+    int32_t dest;
+    int32_t val = (int32_t)valop;
+    int8_t shift = (int8_t)shiftop;
+    if ((shift >= 32) || (shift <= -32)) {
+        dest = 0;
+    } else if (shift < 0) {
+        int64_t big_dest = ((int64_t)val + (1 << (-1 - shift)));
+        dest = big_dest >> -shift;
+    } else {
+        dest = val << shift;
+    }
+    return dest;
+}
+
+/* Handling addition overflow with 64 bits inputs values is more
+ * tricky than with 32 bits values.  */
 uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
@@ -574,7 +593,16 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
         val++;
         val >>= 1;
     } else if (shift < 0) {
-        val = (val + ((int64_t)1 << (-1 - shift))) >> -shift;
+        val >>= (-shift - 1);
+        if (val == INT64_MAX) {
+            /* In this case, it means that the rounding constant is 1,
+             * and the addition would overflow. Return the actual
+             * result directly.  */
+            val = 0x4000000000000000LL;
+        } else {
+            val++;
+            val >>= 1;
+        }
     } else {
         val <<= shift;
     }
@@ -596,9 +624,29 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
     }} while (0)
 NEON_VOP(rshl_u8, neon_u8, 4)
 NEON_VOP(rshl_u16, neon_u16, 2)
-NEON_VOP(rshl_u32, neon_u32, 1)
 #undef NEON_FN
 
+/* The addition of the rounding constant may overflow, so we use an
+ * intermediate 64 bits accumulator.  */
+uint32_t HELPER(neon_rshl_u32)(uint32_t val, uint32_t shiftop)
+{
+    uint32_t dest;
+    int8_t shift = (int8_t)shiftop;
+    if (shift >= 32 || shift < -32) {
+        dest = 0;
+    } else if (shift == -32) {
+        dest = val >> 31;
+    } else if (shift < 0) {
+        uint64_t big_dest = ((uint64_t)val + (1 << (-1 - shift)));
+        dest = big_dest >> -shift;
+    } else {
+        dest = val << shift;
+    }
+    return dest;
+}
+
+/* Handling addition overflow with 64 bits inputs values is more
+ * tricky than with 32 bits values.  */
 uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
@@ -607,9 +655,17 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
     } else if (shift == -64) {
         /* Rounding a 1-bit result just preserves that bit.  */
         val >>= 63;
-    } if (shift < 0) {
-        val = (val + ((uint64_t)1 << (-1 - shift))) >> -shift;
-        val >>= -shift;
+    } else if (shift < 0) {
+        val >>= (-shift - 1);
+        if (val == UINT64_MAX) {
+            /* In this case, it means that the rounding constant is 1,
+             * and the addition would overflow. Return the actual
+             * result directly.  */
+            val = 0x8000000000000000ULL;
+        } else {
+            val++;
+            val >>= 1;
+        }
     } else {
         val <<= shift;
     }
@@ -784,14 +840,43 @@ uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
     }} while (0)
 NEON_VOP_ENV(qrshl_u8, neon_u8, 4)
 NEON_VOP_ENV(qrshl_u16, neon_u16, 2)
-NEON_VOP_ENV(qrshl_u32, neon_u32, 1)
 #undef NEON_FN
 
+/* The addition of the rounding constant may overflow, so we use an
+ * intermediate 64 bits accumulator.  */
+uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop)
+{
+    uint32_t dest;
+    int8_t shift = (int8_t)shiftop;
+    if (shift < 0) {
+        uint64_t big_dest = ((uint64_t)val + (1 << (-1 - shift)));
+        dest = big_dest >> -shift;
+    } else {
+        dest = val << shift;
+        if ((dest >> shift) != val) {
+            SET_QC();
+            dest = ~0;
+        }
+    }
+    return dest;
+}
+
+/* Handling addition overflow with 64 bits inputs values is more
+ * tricky than with 32 bits values.  */
 uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
 {
     int8_t shift = (int8_t)shiftop;
     if (shift < 0) {
-        val = (val + (1 << (-1 - shift))) >> -shift;
+        val >>= (-shift - 1);
+        if (val == UINT64_MAX) {
+            /* In this case, it means that the rounding constant is 1,
+             * and the addition would overflow. Return the actual
+             * result directly.  */
+            val = 0x8000000000000000ULL;
+        } else {
+            val++;
+            val >>= 1;
+        }
     } else { \
         uint64_t tmp = val;
         val <<= shift;
@@ -817,22 +902,52 @@ uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
     }} while (0)
 NEON_VOP_ENV(qrshl_s8, neon_s8, 4)
 NEON_VOP_ENV(qrshl_s16, neon_s16, 2)
-NEON_VOP_ENV(qrshl_s32, neon_s32, 1)
 #undef NEON_FN
 
+/* The addition of the rounding constant may overflow, so we use an
+ * intermediate 64 bits accumulator.  */
+uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+{
+    int32_t dest;
+    int32_t val = (int32_t)valop;
+    int8_t shift = (int8_t)shiftop;
+    if (shift < 0) {
+        int64_t big_dest = ((int64_t)val + (1 << (-1 - shift)));
+        dest = big_dest >> -shift;
+    } else {
+        dest = val << shift;
+        if ((dest >> shift) != val) {
+            SET_QC();
+            dest = (val >> 31) ^ ~SIGNBIT;
+        }
+    }
+    return dest;
+}
+
+/* Handling addition overflow with 64 bits inputs values is more
+ * tricky than with 32 bits values.  */
 uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
 {
     int8_t shift = (uint8_t)shiftop;
     int64_t val = valop;
 
     if (shift < 0) {
-        val = (val + (1 << (-1 - shift))) >> -shift;
+        val >>= (-shift - 1);
+        if (val == INT64_MAX) {
+            /* In this case, it means that the rounding constant is 1,
+             * and the addition would overflow. Return the actual
+             * result directly.  */
+            val = 0x4000000000000000ULL;
+        } else {
+            val++;
+            val >>= 1;
+        }
     } else {
-        int64_t tmp = val;;
+        int64_t tmp = val;
         val <<= shift;
         if ((val >> shift) != tmp) {
             SET_QC();
-            val = tmp >> 31;
+            val = (tmp >> 63) ^ ~SIGNBIT64;
         }
     }
     return val;
commit d68a6f3a6deb2f5eee198b6fa46877a20227d86e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 14 10:22:49 2011 +0000

    target-arm: Move Neon VZIP to helper functions
    
    Move the implementation of the Neon VUZP unzip instruction from inline
    code to helper functions. (At 50+ TCG ops it was well over the
    recommended limit for coding inline.) The helper implementations also
    give the correct answers where the inline implementation did not.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 80251b5..bd6977c 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -466,5 +466,10 @@ DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
 DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
 DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
 DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
+DEF_HELPER_3(neon_zip8, void, env, i32, i32)
+DEF_HELPER_3(neon_zip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 49f1b15..bcc1b4b 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1787,3 +1787,95 @@ void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
     env->vfp.regs[rm] = make_float64(m0);
     env->vfp.regs[rd] = make_float64(d0);
 }
+
+void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8)
+        | (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24)
+        | (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40)
+        | (ELEM(zd0, 3, 8) << 48) | (ELEM(zm0, 3, 8) << 56);
+    uint64_t d1 = ELEM(zd0, 4, 8) | (ELEM(zm0, 4, 8) << 8)
+        | (ELEM(zd0, 5, 8) << 16) | (ELEM(zm0, 5, 8) << 24)
+        | (ELEM(zd0, 6, 8) << 32) | (ELEM(zm0, 6, 8) << 40)
+        | (ELEM(zd0, 7, 8) << 48) | (ELEM(zm0, 7, 8) << 56);
+    uint64_t m0 = ELEM(zd1, 0, 8) | (ELEM(zm1, 0, 8) << 8)
+        | (ELEM(zd1, 1, 8) << 16) | (ELEM(zm1, 1, 8) << 24)
+        | (ELEM(zd1, 2, 8) << 32) | (ELEM(zm1, 2, 8) << 40)
+        | (ELEM(zd1, 3, 8) << 48) | (ELEM(zm1, 3, 8) << 56);
+    uint64_t m1 = ELEM(zd1, 4, 8) | (ELEM(zm1, 4, 8) << 8)
+        | (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24)
+        | (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40)
+        | (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16)
+        | (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48);
+    uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16)
+        | (ELEM(zd0, 3, 16) << 32) | (ELEM(zm0, 3, 16) << 48);
+    uint64_t m0 = ELEM(zd1, 0, 16) | (ELEM(zm1, 0, 16) << 16)
+        | (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48);
+    uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16)
+        | (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32);
+    uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32);
+    uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32);
+    uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm = float64_val(env->vfp.regs[rm]);
+    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8)
+        | (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24)
+        | (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40)
+        | (ELEM(zd, 3, 8) << 48) | (ELEM(zm, 3, 8) << 56);
+    uint64_t m0 = ELEM(zd, 4, 8) | (ELEM(zm, 4, 8) << 8)
+        | (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24)
+        | (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40)
+        | (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rd] = make_float64(d0);
+}
+
+void HELPER(neon_zip16)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm = float64_val(env->vfp.regs[rm]);
+    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16)
+        | (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48);
+    uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16)
+        | (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rd] = make_float64(d0);
+}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 398764e..16d2ebf 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3653,59 +3653,43 @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
     return 0;
 }
 
-static void gen_neon_zip_u8(TCGv t0, TCGv t1)
-{
-    TCGv rd, rm, tmp;
-
-    rd = new_tmp();
-    rm = new_tmp();
-    tmp = new_tmp();
-
-    tcg_gen_andi_i32(rd, t0, 0xff);
-    tcg_gen_shli_i32(tmp, t1, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff00);
-    tcg_gen_or_i32(rd, rd, tmp);
-    tcg_gen_shli_i32(tmp, t0, 16);
-    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
-    tcg_gen_or_i32(rd, rd, tmp);
-    tcg_gen_shli_i32(tmp, t1, 24);
-    tcg_gen_andi_i32(tmp, tmp, 0xff000000);
-    tcg_gen_or_i32(rd, rd, tmp);
-
-    tcg_gen_andi_i32(rm, t1, 0xff000000);
-    tcg_gen_shri_i32(tmp, t0, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
-    tcg_gen_or_i32(rm, rm, tmp);
-    tcg_gen_shri_i32(tmp, t1, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff00);
-    tcg_gen_or_i32(rm, rm, tmp);
-    tcg_gen_shri_i32(tmp, t0, 16);
-    tcg_gen_andi_i32(tmp, tmp, 0xff);
-    tcg_gen_or_i32(t1, rm, tmp);
-    tcg_gen_mov_i32(t0, rd);
-
-    dead_tmp(tmp);
-    dead_tmp(rm);
-    dead_tmp(rd);
-}
-
-static void gen_neon_zip_u16(TCGv t0, TCGv t1)
+static int gen_neon_zip(int rd, int rm, int size, int q)
 {
     TCGv tmp, tmp2;
-
-    tmp = new_tmp();
-    tmp2 = new_tmp();
-
-    tcg_gen_andi_i32(tmp, t0, 0xffff);
-    tcg_gen_shli_i32(tmp2, t1, 16);
-    tcg_gen_or_i32(tmp, tmp, tmp2);
-    tcg_gen_andi_i32(t1, t1, 0xffff0000);
-    tcg_gen_shri_i32(tmp2, t0, 16);
-    tcg_gen_or_i32(t1, t1, tmp2);
-    tcg_gen_mov_i32(t0, tmp);
-
-    dead_tmp(tmp2);
-    dead_tmp(tmp);
+    if (size == 3 || (!q && size == 2)) {
+        return 1;
+    }
+    tmp = tcg_const_i32(rd);
+    tmp2 = tcg_const_i32(rm);
+    if (q) {
+        switch (size) {
+        case 0:
+            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
+            break;
+        case 1:
+            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
+            break;
+        case 2:
+            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
+            break;
+        default:
+            abort();
+        }
+    } else {
+        switch (size) {
+        case 0:
+            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
+            break;
+        case 1:
+            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
+            break;
+        default:
+            abort();
+        }
+    }
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(tmp2);
+    return 0;
 }
 
 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
@@ -5429,29 +5413,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                     break;
                 case 35: /* VZIP */
-                    /* Reg  Before       After
-                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
-                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
-                     */
-                    if (size == 3)
+                    if (gen_neon_zip(rd, rm, size, q)) {
                         return 1;
-                    count = (q ? 4 : 2);
-                    for (n = 0; n < count; n++) {
-                        tmp = neon_load_reg(rd, n);
-                        tmp2 = neon_load_reg(rd, n);
-                        switch (size) {
-                        case 0: gen_neon_zip_u8(tmp, tmp2); break;
-                        case 1: gen_neon_zip_u16(tmp, tmp2); break;
-                        case 2: /* no-op */; break;
-                        default: abort();
-                        }
-                        neon_store_scratch(n * 2, tmp);
-                        neon_store_scratch(n * 2 + 1, tmp2);
-                    }
-                    for (n = 0; n < count * 2; n++) {
-                        int reg = (n < count) ? rd : rm;
-                        tmp = neon_load_scratch(n);
-                        neon_store_reg(reg, n % count, tmp);
                     }
                     break;
                 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
commit 02acedf93da420713a0c4bbeaf32ce9d734a4332
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Feb 14 10:22:48 2011 +0000

    target-arm: Move Neon VUZP to helper functions
    
    Move the implementation of the Neon VUZP unzip instruction from inline
    code to helper functions. (At 50+ TCG ops it was well over the
    recommended limit for coding inline.) The helper implementations also
    fix the handling of the quadword version of the instruction.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 18b488b..80251b5 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -461,4 +461,10 @@ DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 
 DEF_HELPER_2(set_teecr, void, env, i32)
 
+DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
+DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
+
 #include "def-helper.h"
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index ee253bb..49f1b15 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1693,3 +1693,97 @@ uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
     float32 f1 = float32_abs(vfp_itos(b));
     return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0;
 }
+
+#define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
+
+void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8)
+        | (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24)
+        | (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40)
+        | (ELEM(zd1, 4, 8) << 48) | (ELEM(zd1, 6, 8) << 56);
+    uint64_t d1 = ELEM(zm0, 0, 8) | (ELEM(zm0, 2, 8) << 8)
+        | (ELEM(zm0, 4, 8) << 16) | (ELEM(zm0, 6, 8) << 24)
+        | (ELEM(zm1, 0, 8) << 32) | (ELEM(zm1, 2, 8) << 40)
+        | (ELEM(zm1, 4, 8) << 48) | (ELEM(zm1, 6, 8) << 56);
+    uint64_t m0 = ELEM(zd0, 1, 8) | (ELEM(zd0, 3, 8) << 8)
+        | (ELEM(zd0, 5, 8) << 16) | (ELEM(zd0, 7, 8) << 24)
+        | (ELEM(zd1, 1, 8) << 32) | (ELEM(zd1, 3, 8) << 40)
+        | (ELEM(zd1, 5, 8) << 48) | (ELEM(zd1, 7, 8) << 56);
+    uint64_t m1 = ELEM(zm0, 1, 8) | (ELEM(zm0, 3, 8) << 8)
+        | (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24)
+        | (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40)
+        | (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16)
+        | (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48);
+    uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16)
+        | (ELEM(zm1, 0, 16) << 32) | (ELEM(zm1, 2, 16) << 48);
+    uint64_t m0 = ELEM(zd0, 1, 16) | (ELEM(zd0, 3, 16) << 16)
+        | (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48);
+    uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16)
+        | (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm0 = float64_val(env->vfp.regs[rm]);
+    uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
+    uint64_t zd0 = float64_val(env->vfp.regs[rd]);
+    uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
+    uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32);
+    uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32);
+    uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32);
+    uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rm + 1] = make_float64(m1);
+    env->vfp.regs[rd] = make_float64(d0);
+    env->vfp.regs[rd + 1] = make_float64(d1);
+}
+
+void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm = float64_val(env->vfp.regs[rm]);
+    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8)
+        | (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24)
+        | (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40)
+        | (ELEM(zm, 4, 8) << 48) | (ELEM(zm, 6, 8) << 56);
+    uint64_t m0 = ELEM(zd, 1, 8) | (ELEM(zd, 3, 8) << 8)
+        | (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24)
+        | (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40)
+        | (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rd] = make_float64(d0);
+}
+
+void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm)
+{
+    uint64_t zm = float64_val(env->vfp.regs[rm]);
+    uint64_t zd = float64_val(env->vfp.regs[rd]);
+    uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16)
+        | (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48);
+    uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16)
+        | (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48);
+    env->vfp.regs[rm] = make_float64(m0);
+    env->vfp.regs[rd] = make_float64(d0);
+}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f348820..398764e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3614,40 +3614,43 @@ static inline TCGv neon_get_scalar(int size, int reg)
     return tmp;
 }
 
-static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
+static int gen_neon_unzip(int rd, int rm, int size, int q)
 {
-    TCGv rd, rm, tmp;
-
-    rd = new_tmp();
-    rm = new_tmp();
-    tmp = new_tmp();
-
-    tcg_gen_andi_i32(rd, t0, 0xff);
-    tcg_gen_shri_i32(tmp, t0, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff00);
-    tcg_gen_or_i32(rd, rd, tmp);
-    tcg_gen_shli_i32(tmp, t1, 16);
-    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
-    tcg_gen_or_i32(rd, rd, tmp);
-    tcg_gen_shli_i32(tmp, t1, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff000000);
-    tcg_gen_or_i32(rd, rd, tmp);
-
-    tcg_gen_shri_i32(rm, t0, 8);
-    tcg_gen_andi_i32(rm, rm, 0xff);
-    tcg_gen_shri_i32(tmp, t0, 16);
-    tcg_gen_andi_i32(tmp, tmp, 0xff00);
-    tcg_gen_or_i32(rm, rm, tmp);
-    tcg_gen_shli_i32(tmp, t1, 8);
-    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
-    tcg_gen_or_i32(rm, rm, tmp);
-    tcg_gen_andi_i32(tmp, t1, 0xff000000);
-    tcg_gen_or_i32(t1, rm, tmp);
-    tcg_gen_mov_i32(t0, rd);
-
-    dead_tmp(tmp);
-    dead_tmp(rm);
-    dead_tmp(rd);
+    TCGv tmp, tmp2;
+    if (size == 3 || (!q && size == 2)) {
+        return 1;
+    }
+    tmp = tcg_const_i32(rd);
+    tmp2 = tcg_const_i32(rm);
+    if (q) {
+        switch (size) {
+        case 0:
+            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
+            break;
+        case 1:
+            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
+            break;
+        case 2:
+            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
+            break;
+        default:
+            abort();
+        }
+    } else {
+        switch (size) {
+        case 0:
+            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
+            break;
+        case 1:
+            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
+            break;
+        default:
+            abort();
+        }
+    }
+    tcg_temp_free_i32(tmp);
+    tcg_temp_free_i32(tmp2);
+    return 0;
 }
 
 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
@@ -3705,25 +3708,6 @@ static void gen_neon_zip_u16(TCGv t0, TCGv t1)
     dead_tmp(tmp);
 }
 
-static void gen_neon_unzip(int reg, int q, int tmp, int size)
-{
-    int n;
-    TCGv t0, t1;
-
-    for (n = 0; n < q + 1; n += 2) {
-        t0 = neon_load_reg(reg, n);
-        t1 = neon_load_reg(reg, n + 1);
-        switch (size) {
-        case 0: gen_neon_unzip_u8(t0, t1); break;
-        case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same.  */
-        case 2: /* no-op */; break;
-        default: abort();
-        }
-        neon_store_scratch(tmp + n, t0);
-        neon_store_scratch(tmp + n + 1, t1);
-    }
-}
-
 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
 {
     TCGv rd, tmp;
@@ -5440,30 +5424,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     }
                     break;
                 case 34: /* VUZP */
-                    /* Reg  Before       After
-                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
-                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
-                     */
-                    if (size == 3)
+                    if (gen_neon_unzip(rd, rm, size, q)) {
                         return 1;
-                    gen_neon_unzip(rd, q, 0, size);
-                    gen_neon_unzip(rm, q, 4, size);
-                    if (q) {
-                        static int unzip_order_q[8] =
-                            {0, 2, 4, 6, 1, 3, 5, 7};
-                        for (n = 0; n < 8; n++) {
-                            int reg = (n < 4) ? rd : rm;
-                            tmp = neon_load_scratch(unzip_order_q[n]);
-                            neon_store_reg(reg, n % 4, tmp);
-                        }
-                    } else {
-                        static int unzip_order[4] =
-                            {0, 4, 1, 5};
-                        for (n = 0; n < 4; n++) {
-                            int reg = (n < 2) ? rd : rm;
-                            tmp = neon_load_scratch(unzip_order[n]);
-                            neon_store_reg(reg, n % 2, tmp);
-                        }
                     }
                     break;
                 case 35: /* VZIP */
commit f06053e3c3933f75df9694aa3970d589f88b3543
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Fri Feb 11 13:35:25 2011 +0000

    target-arm: Correct conversion of Thumb Neon dp encodings into ARM
    
    We handle Thumb Neon data processing instructions by converting them
    into the equivalent ARM encoding, as the two are very close. However
    the ARM encoding should have bit 28 set, not clear. This wasn't causing
    any problems because we don't actually look at that bit during decode;
    however it is better to do the conversion correctly to avoid problems
    later if we add checks to UNDEF on SBZ/SBO bits.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 83dc180..f348820 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8015,7 +8015,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
         /* Coprocessor.  */
         if (((insn >> 24) & 3) == 3) {
             /* Translate into the equivalent ARM encoding.  */
-            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
+            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
             if (disas_neon_data_insn(env, s, insn))
                 goto illegal_op;
         } else {
commit 4dc064e66e38afbada08fa739ed7d03f7227ff72
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 11 12:26:48 2011 +0000

    target-arm: Fix Neon VQDMLSL instruction
    
    For VQDMLSL, negation has to occur after saturation, not before.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index a44e84c..83dc180 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5137,16 +5137,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg64(cpu_V0, rd + pass);
                     } else if (op == 5 || (op >= 8 && op <= 11)) {
                         /* Accumulate.  */
-                        if (op == 10 || op == 11) {
-                            gen_neon_negl(cpu_V0, size);
-                        }
                         neon_load_reg64(cpu_V1, rd + pass);
                         switch (op) {
-                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
+                        case 10: /* VMLSL */
+                            gen_neon_negl(cpu_V0, size);
+                            /* Fall through */
+                        case 5: case 8: /* VABAL, VMLAL */
                             gen_neon_addl(size);
                             break;
                         case 9: case 11: /* VQDMLAL, VQDMLSL */
                             gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
+                            if (op == 11) {
+                                gen_neon_negl(cpu_V0, size);
+                            }
                             gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
                             break;
                         default:
@@ -5284,18 +5287,21 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tmp2 = tmp4;
                         }
                         gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
-                        if (op == 6 || op == 7) {
-                            gen_neon_negl(cpu_V0, size);
-                        }
                         if (op != 11) {
                             neon_load_reg64(cpu_V1, rd + pass);
                         }
                         switch (op) {
-                        case 2: case 6:
+                        case 6:
+                            gen_neon_negl(cpu_V0, size);
+                            /* Fall through */
+                        case 2:
                             gen_neon_addl(size);
                             break;
                         case 3: case 7:
                             gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
+                            if (op == 7) {
+                                gen_neon_negl(cpu_V0, size);
+                            }
                             gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
                             break;
                         case 10:
commit ebcd88ceb5da70ee17c1d22e9874524649335759
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 11 12:26:47 2011 +0000

    target-arm: Refactor handling of VQDMULL
    
    Refactor the handling of VQDMULL so that it is dealt with in
    its own if() case rather than together with the accumulating
    instructions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0c93896..a44e84c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5131,16 +5131,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     default: /* 15 is RESERVED.  */
                         return 1;
                     }
-                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
+                    if (op == 13) {
+                        /* VQDMULL */
+                        gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
+                        neon_store_reg64(cpu_V0, rd + pass);
+                    } else if (op == 5 || (op >= 8 && op <= 11)) {
                         /* Accumulate.  */
                         if (op == 10 || op == 11) {
                             gen_neon_negl(cpu_V0, size);
                         }
-
-                        if (op != 13) {
-                            neon_load_reg64(cpu_V1, rd + pass);
-                        }
-
+                        neon_load_reg64(cpu_V1, rd + pass);
                         switch (op) {
                         case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
                             gen_neon_addl(size);
@@ -5149,10 +5149,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
                             gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
                             break;
-                            /* Fall through.  */
-                        case 13: /* VQDMULL */
-                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
-                            break;
                         default:
                             abort();
                         }
commit e5ca24cba969b58eb3fe0e7c239df3abe21831c0
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 10 19:07:55 2011 +0000

    target-arm: Implement VMULL.P8
    
    Implement VMULL.P8 (the 32x32->64 version of the polynomial multiply
    instruction).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 77f1635..18b488b 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -277,6 +277,7 @@ DEF_HELPER_2(neon_sub_u16, i32, i32, i32)
 DEF_HELPER_2(neon_mul_u8, i32, i32, i32)
 DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
 DEF_HELPER_2(neon_mul_p8, i32, i32, i32)
+DEF_HELPER_2(neon_mull_p8, i64, i32, i32)
 
 DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
 DEF_HELPER_2(neon_tst_u16, i32, i32, i32)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index dc09968..ee253bb 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -895,6 +895,36 @@ uint32_t HELPER(neon_mul_p8)(uint32_t op1, uint32_t op2)
     return result;
 }
 
+uint64_t HELPER(neon_mull_p8)(uint32_t op1, uint32_t op2)
+{
+    uint64_t result = 0;
+    uint64_t mask;
+    uint64_t op2ex = op2;
+    op2ex = (op2ex & 0xff) |
+        ((op2ex & 0xff00) << 8) |
+        ((op2ex & 0xff0000) << 16) |
+        ((op2ex & 0xff000000) << 24);
+    while (op1) {
+        mask = 0;
+        if (op1 & 1) {
+            mask |= 0xffff;
+        }
+        if (op1 & (1 << 8)) {
+            mask |= (0xffffU << 16);
+        }
+        if (op1 & (1 << 16)) {
+            mask |= (0xffffULL << 32);
+        }
+        if (op1 & (1 << 24)) {
+            mask |= (0xffffULL << 48);
+        }
+        result ^= op2ex & mask;
+        op1 = (op1 >> 1) & 0x7f7f7f7f;
+        op2ex <<= 1;
+    }
+    return result;
+}
+
 #define NEON_FN(dest, src1, src2) dest = (src1 & src2) ? -1 : 0
 NEON_VOP(tst_u8, neon_u8, 4)
 NEON_VOP(tst_u16, neon_u16, 2)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 362d1d0..0c93896 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5124,8 +5124,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
                         break;
                     case 14: /* Polynomial VMULL */
-                        cpu_abort(env, "Polynomial VMULL not implemented");
-
+                        gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
+                        dead_tmp(tmp2);
+                        dead_tmp(tmp);
+                        break;
                     default: /* 15 is RESERVED.  */
                         return 1;
                     }
commit 02615337ef295443daa03233e492194e289a807e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jan 31 18:26:40 2011 +0000

    qemu-lock.h: Remove non-pthreads spinlock implementations
    
    Since configure guarantees us that we have pthreads on all hosts
    except mingw (which doesn't support a USER_ONLY config), we can
    and should use the pthread_mutex based implementation of spin_lock()
    and spin_unlock() in all USER_ONLY cases. This means that all the
    inline-native-assembly code supporting the "USER_ONLY but not USE_NPTL"
    case can go away.
    
    The not-USER_ONLY case remains as empty implementations; there is
    no change in behaviour here.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/qemu-lock.h b/qemu-lock.h
index 65ca084..a72edda 100644
--- a/qemu-lock.h
+++ b/qemu-lock.h
@@ -15,15 +15,11 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-/* Locking primitives.  Most of this code should be redundant -
-   system emulation doesn't need/use locking, NPTL userspace uses
-   pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
-   In either case a spinlock is probably the wrong kind of lock.
-   Spinlocks are only good if you know annother CPU has the lock and is
-   likely to release it soon.  In environments where you have more threads
-   than physical CPUs (the extreme case being a single CPU host) a spinlock
-   simply wastes CPU until the OS decides to preempt it.  */
-#if defined(CONFIG_USE_NPTL)
+/* configure guarantees us that we have pthreads on any host except
+ * mingw32, which doesn't support any of the user-only targets.
+ * So we can simply assume we have pthread mutexes here.
+ */
+#if defined(CONFIG_USER_ONLY)
 
 #include <pthread.h>
 #define spin_lock pthread_mutex_lock
@@ -33,198 +29,15 @@
 
 #else
 
-#if defined(__hppa__)
-
-typedef int spinlock_t[4];
-
-#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
-
-static inline void resetlock (spinlock_t *p)
-{
-    (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
-}
-
-#else
-
+/* Empty implementations, on the theory that system mode emulation
+ * is single-threaded. This means that these functions should only
+ * be used from code run in the TCG cpu thread, and cannot protect
+ * data structures which might also be accessed from the IO thread
+ * or from signal handlers.
+ */
 typedef int spinlock_t;
-
 #define SPIN_LOCK_UNLOCKED 0
 
-static inline void resetlock (spinlock_t *p)
-{
-    *p = SPIN_LOCK_UNLOCKED;
-}
-
-#endif
-
-#if defined(_ARCH_PPC)
-static inline int testandset (int *p)
-{
-    int ret;
-    __asm__ __volatile__ (
-                          "      lwarx %0,0,%1\n"
-                          "      xor. %0,%3,%0\n"
-                          "      bne $+12\n"
-                          "      stwcx. %2,0,%1\n"
-                          "      bne- $-16\n"
-                          : "=&r" (ret)
-                          : "r" (p), "r" (1), "r" (0)
-                          : "cr0", "memory");
-    return ret;
-}
-#elif defined(__i386__)
-static inline int testandset (int *p)
-{
-    long int readval = 0;
-
-    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
-                          : "+m" (*p), "+a" (readval)
-                          : "r" (1)
-                          : "cc");
-    return readval;
-}
-#elif defined(__x86_64__)
-static inline int testandset (int *p)
-{
-    long int readval = 0;
-
-    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
-                          : "+m" (*p), "+a" (readval)
-                          : "r" (1)
-                          : "cc");
-    return readval;
-}
-#elif defined(__s390__)
-static inline int testandset (int *p)
-{
-    int ret;
-
-    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
-			  "   jl    0b"
-			  : "=&d" (ret)
-			  : "r" (1), "a" (p), "0" (*p)
-			  : "cc", "memory" );
-    return ret;
-}
-#elif defined(__alpha__)
-static inline int testandset (int *p)
-{
-    int ret;
-    unsigned long one;
-
-    __asm__ __volatile__ ("0:	mov 1,%2\n"
-			  "	ldl_l %0,%1\n"
-			  "	stl_c %2,%1\n"
-			  "	beq %2,1f\n"
-			  ".subsection 2\n"
-			  "1:	br 0b\n"
-			  ".previous"
-			  : "=r" (ret), "=m" (*p), "=r" (one)
-			  : "m" (*p));
-    return ret;
-}
-#elif defined(__sparc__)
-static inline int testandset (int *p)
-{
-	int ret;
-
-	__asm__ __volatile__("ldstub	[%1], %0"
-			     : "=r" (ret)
-			     : "r" (p)
-			     : "memory");
-
-	return (ret ? 1 : 0);
-}
-#elif defined(__arm__)
-static inline int testandset (int *spinlock)
-{
-    register unsigned int ret;
-    __asm__ __volatile__("swp %0, %1, [%2]"
-                         : "=r"(ret)
-                         : "0"(1), "r"(spinlock));
-
-    return ret;
-}
-#elif defined(__mc68000)
-static inline int testandset (int *p)
-{
-    char ret;
-    __asm__ __volatile__("tas %1; sne %0"
-                         : "=r" (ret)
-                         : "m" (p)
-                         : "cc","memory");
-    return ret;
-}
-#elif defined(__hppa__)
-
-/* Because malloc only guarantees 8-byte alignment for malloc'd data,
-   and GCC only guarantees 8-byte alignment for stack locals, we can't
-   be assured of 16-byte alignment for atomic lock data even if we
-   specify "__attribute ((aligned(16)))" in the type declaration.  So,
-   we use a struct containing an array of four ints for the atomic lock
-   type and dynamically select the 16-byte aligned int from the array
-   for the semaphore.  */
-#define __PA_LDCW_ALIGNMENT 16
-static inline void *ldcw_align (void *p) {
-    unsigned long a = (unsigned long)p;
-    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
-    return (void *)a;
-}
-
-static inline int testandset (spinlock_t *p)
-{
-    unsigned int ret;
-    p = ldcw_align(p);
-    __asm__ __volatile__("ldcw 0(%1),%0"
-                         : "=r" (ret)
-                         : "r" (p)
-                         : "memory" );
-    return !ret;
-}
-
-#elif defined(__ia64)
-
-#include <ia64intrin.h>
-
-static inline int testandset (int *p)
-{
-    return __sync_lock_test_and_set (p, 1);
-}
-#elif defined(__mips__)
-static inline int testandset (int *p)
-{
-    int ret;
-
-    __asm__ __volatile__ (
-	"	.set push		\n"
-	"	.set noat		\n"
-	"	.set mips2		\n"
-	"1:	li	$1, 1		\n"
-	"	ll	%0, %1		\n"
-	"	sc	$1, %1		\n"
-	"	beqz	$1, 1b		\n"
-	"	.set pop		"
-	: "=r" (ret), "+R" (*p)
-	:
-	: "memory");
-
-    return ret;
-}
-#else
-#error unimplemented CPU support
-#endif
-
-#if defined(CONFIG_USER_ONLY)
-static inline void spin_lock(spinlock_t *lock)
-{
-    while (testandset(lock));
-}
-
-static inline void spin_unlock(spinlock_t *lock)
-{
-    resetlock(lock);
-}
-#else
 static inline void spin_lock(spinlock_t *lock)
 {
 }
@@ -232,6 +45,5 @@ static inline void spin_lock(spinlock_t *lock)
 static inline void spin_unlock(spinlock_t *lock)
 {
 }
-#endif
 
 #endif
commit 322fd48afbed1ef7b834ac343a0c8687bcb33695
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 15 18:27:55 2011 +0200

    e1000: verify we have buffers, upfront
    
    The spec says: Any descriptor with a non-zero status byte has been
    processed by the hardware, and is ready to be handled by the software.
    
    Thus, once we change a descriptor status to non-zero we should
    never move the head backwards and try to reuse this
    descriptor from hardware.
    
    This actually happened with a multibuffer packet
    that arrives when we don't have enough buffers.
    
    Fix by checking that we have enough buffers upfront
    so we never need to discard the packet midway through.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/e1000.c b/hw/e1000.c
index 2943a1a..0a4574c 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -631,6 +631,24 @@ e1000_can_receive(VLANClientState *nc)
     return (s->mac_reg[RCTL] & E1000_RCTL_EN);
 }
 
+static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
+{
+    int bufs;
+    /* Fast-path short packets */
+    if (total_size <= s->rxbuf_size) {
+        return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov;
+    }
+    if (s->mac_reg[RDH] < s->mac_reg[RDT]) {
+        bufs = s->mac_reg[RDT] - s->mac_reg[RDH];
+    } else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) {
+        bufs = s->mac_reg[RDLEN] /  sizeof(struct e1000_rx_desc) +
+            s->mac_reg[RDT] - s->mac_reg[RDH];
+    } else {
+        return false;
+    }
+    return total_size <= bufs * s->rxbuf_size;
+}
+
 static ssize_t
 e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
@@ -671,17 +689,15 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     rdh_start = s->mac_reg[RDH];
     desc_offset = 0;
     total_size = size + fcs_len(s);
+    if (!e1000_has_rxbufs(s, total_size)) {
+            set_ics(s, 0, E1000_ICS_RXO);
+            return -1;
+    }
     do {
         desc_size = total_size - desc_offset;
         if (desc_size > s->rxbuf_size) {
             desc_size = s->rxbuf_size;
         }
-        if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
-            /* Discard all data written so far */
-            s->mac_reg[RDH] = rdh_start;
-            set_ics(s, 0, E1000_ICS_RXO);
-            return -1;
-        }
         base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +
                sizeof(desc) * s->mac_reg[RDH];
         cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
commit ee912ccfa007351a62ba42bd60499769f6c02c1e
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 15 18:27:52 2011 +0200

    e1000: clear EOP for multi-buffer descriptors
    
    The e1000 spec says: if software statically allocates
    buffers, and uses memory read to check for completed descriptors, it
    simply has to zero the status byte in the descriptor to make it ready
    for reuse by hardware. This is not a hardware requirement (moving the
    hardware tail pointer is), but is necessary for performing an in–memory
    scan.
    
    Thus the guest does not have to clear the status byte.  In case it
    doesn't we need to clear EOP for all descriptors
    except the last.  While I don't know of any such guests,
    it's probably a good idea to stick to the spec.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reported-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/e1000.c b/hw/e1000.c
index 050ce02..2943a1a 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -698,11 +698,13 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
                                           copy_size);
             }
             desc_offset += desc_size;
+            desc.length = cpu_to_le16(desc_size);
             if (desc_offset >= total_size) {
-                desc.length = cpu_to_le16(desc_size);
                 desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM;
             } else {
-                desc.length = cpu_to_le16(desc_size);
+                /* Guest zeroing out status is not a hardware requirement.
+                   Clear EOP in case guest didn't do it. */
+                desc.status &= ~E1000_RXD_STAT_EOP;
             }
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
commit b19487e27ed3009df7f555998a454ba19aefd4b8
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 15 18:27:48 2011 +0200

    e1000: multi-buffer packet support
    
    e1000 supports multi-buffer packets larger than rxbuf_size.
    
    This fixes the following (on linux):
    - in guest: ifconfig eth1 mtu 16110
    - in host: ifconfig tap0 mtu 16110
               ping -s 16082 <guest-ip>
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/e1000.c b/hw/e1000.c
index af101bd..050ce02 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -642,6 +642,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     uint16_t vlan_special = 0;
     uint8_t vlan_status = 0, vlan_offset = 0;
     uint8_t min_buf[MIN_BUF_SIZE];
+    size_t desc_offset;
+    size_t desc_size;
+    size_t total_size;
 
     if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
         return -1;
@@ -654,12 +657,6 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         size = sizeof(min_buf);
     }
 
-    if (size > s->rxbuf_size) {
-        DBGOUT(RX, "packet too large for buffers (%lu > %d)\n",
-               (unsigned long)size, s->rxbuf_size);
-        return -1;
-    }
-
     if (!receive_filter(s, buf, size))
         return size;
 
@@ -672,8 +669,16 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     }
 
     rdh_start = s->mac_reg[RDH];
+    desc_offset = 0;
+    total_size = size + fcs_len(s);
     do {
+        desc_size = total_size - desc_offset;
+        if (desc_size > s->rxbuf_size) {
+            desc_size = s->rxbuf_size;
+        }
         if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
+            /* Discard all data written so far */
+            s->mac_reg[RDH] = rdh_start;
             set_ics(s, 0, E1000_ICS_RXO);
             return -1;
         }
@@ -683,10 +688,22 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
         desc.special = vlan_special;
         desc.status |= (vlan_status | E1000_RXD_STAT_DD);
         if (desc.buffer_addr) {
-            cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
-                                      (void *)(buf + vlan_offset), size);
-            desc.length = cpu_to_le16(size + fcs_len(s));
-            desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
+            if (desc_offset < size) {
+                size_t copy_size = size - desc_offset;
+                if (copy_size > s->rxbuf_size) {
+                    copy_size = s->rxbuf_size;
+                }
+                cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
+                                          (void *)(buf + desc_offset + vlan_offset),
+                                          copy_size);
+            }
+            desc_offset += desc_size;
+            if (desc_offset >= total_size) {
+                desc.length = cpu_to_le16(desc_size);
+                desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM;
+            } else {
+                desc.length = cpu_to_le16(desc_size);
+            }
         } else { // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
         }
@@ -702,7 +719,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
             set_ics(s, 0, E1000_ICS_RXO);
             return -1;
         }
-    } while (desc.buffer_addr == 0);
+    } while (desc_offset < total_size);
 
     s->mac_reg[GPRC]++;
     s->mac_reg[TPR]++;
commit 1c69371006084f4d1b63283ac94a87d17dfdfb11
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Feb 9 19:35:51 2011 +0100

    pc: remove test on TARGET_PHYS_ADDR_BITS == 32
    
    Both i386 and x86_64 targets are now using target_phys_bits=64. Remove
    useless code.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pc.c b/hw/pc.c
index 3d7e036..5966bf1 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -980,11 +980,6 @@ void pc_memory_init(ram_addr_t ram_size,
     *above_4g_mem_size_p = above_4g_mem_size;
     *below_4g_mem_size_p = below_4g_mem_size;
 
-#if TARGET_PHYS_ADDR_BITS == 32
-    if (above_4g_mem_size > 0) {
-        hw_error("To much RAM for 32-bit physical address");
-    }
-#endif
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
@@ -994,12 +989,10 @@ void pc_memory_init(ram_addr_t ram_size,
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
                  ram_addr + 0x100000);
-#if TARGET_PHYS_ADDR_BITS > 32
     if (above_4g_mem_size > 0) {
         cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
                                      ram_addr + below_4g_mem_size);
     }
-#endif
 
     /* BIOS load */
     if (bios_name == NULL)
commit 71deff27492fb97b0515492bc7ec2a38c6c27dde
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Feb 9 19:35:50 2011 +0100

    target-i386: set target_phys_bits to 64
    
    qemu i386 used to support more than 4GB of RAM through PAE, but it has
    been disabled for an unknown reason. Reenable it.
    
    Note that simply running qemu x86_64 and emulating a 32-bit CPU is not
    a solution to this problem as it is about 15% slower (it needs to
    emulate 64 bit registers even if half of them are not used). On the
    other hand, I haven't seen any measurable impact by switching
    target_phys_bits to 64.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index fe00036..e3cecca 100755
--- a/configure
+++ b/configure
@@ -2973,7 +2973,7 @@ TARGET_ABI_DIR=""
 
 case "$target_arch2" in
   i386)
-    target_phys_bits=32
+    target_phys_bits=64
   ;;
   x86_64)
     TARGET_BASE_ARCH=i386
commit 0899965f6841ff96fcfe1fd766e95216af96b33e
Merge: 64d7e9a... 80f5ce7...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Feb 20 14:47:48 2011 +0100

    Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
    
    * 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
      linux-user: correct core dump format
      linux-user: Define target alignment size
      linux-user: Support the epoll syscalls
      linux-user: in linux-user/strace.c, tswap() is useless
      linux-user: add rmdir() strace

commit 64d7e9a421fea0ac50b44541f5521de455e7cd5d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Feb 13 19:54:40 2011 +0000

    i8254: convert to qdev
    
    Convert to qdev. Don't expose PITState.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8254.c b/hw/i8254.c
index 06b225c..680caab 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -53,9 +53,12 @@ typedef struct PITChannelState {
     qemu_irq irq;
 } PITChannelState;
 
-struct PITState {
+typedef struct PITState {
+    ISADevice dev;
+    uint32_t irq;
+    uint32_t iobase;
     PITChannelState channels[3];
-};
+} PITState;
 
 static PITState pit_state;
 
@@ -119,8 +122,9 @@ static int pit_get_out1(PITChannelState *s, int64_t current_time)
     return out;
 }
 
-int pit_get_out(PITState *pit, int channel, int64_t current_time)
+int pit_get_out(ISADevice *dev, int channel, int64_t current_time)
 {
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s = &pit->channels[channel];
     return pit_get_out1(s, current_time);
 }
@@ -179,8 +183,9 @@ static int64_t pit_get_next_transition_time(PITChannelState *s,
 }
 
 /* val must be 0 or 1 */
-void pit_set_gate(PITState *pit, int channel, int val)
+void pit_set_gate(ISADevice *dev, int channel, int val)
 {
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s = &pit->channels[channel];
 
     switch(s->mode) {
@@ -210,20 +215,23 @@ void pit_set_gate(PITState *pit, int channel, int val)
     s->gate = val;
 }
 
-int pit_get_gate(PITState *pit, int channel)
+int pit_get_gate(ISADevice *dev, int channel)
 {
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s = &pit->channels[channel];
     return s->gate;
 }
 
-int pit_get_initial_count(PITState *pit, int channel)
+int pit_get_initial_count(ISADevice *dev, int channel)
 {
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s = &pit->channels[channel];
     return s->count;
 }
 
-int pit_get_mode(PITState *pit, int channel)
+int pit_get_mode(ISADevice *dev, int channel)
 {
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s = &pit->channels[channel];
     return s->mode;
 }
@@ -462,9 +470,9 @@ static const VMStateDescription vmstate_pit = {
     }
 };
 
-static void pit_reset(void *opaque)
+static void pit_reset(DeviceState *dev)
 {
-    PITState *pit = opaque;
+    PITState *pit = container_of(dev, PITState, dev.qdev);
     PITChannelState *s;
     int i;
 
@@ -498,20 +506,39 @@ void hpet_pit_enable(void)
     pit_load_count(s, 0);
 }
 
-PITState *pit_init(int base, qemu_irq irq)
+static int pit_initfn(ISADevice *dev)
 {
-    PITState *pit = &pit_state;
+    PITState *pit = DO_UPCAST(PITState, dev, dev);
     PITChannelState *s;
 
     s = &pit->channels[0];
     /* the timer 0 is connected to an IRQ */
     s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
-    s->irq = irq;
+    s->irq = isa_reserve_irq(pit->irq);
 
-    vmstate_register(NULL, base, &vmstate_pit, pit);
-    qemu_register_reset(pit_reset, pit);
-    register_ioport_write(base, 4, 1, pit_ioport_write, pit);
-    register_ioport_read(base, 3, 1, pit_ioport_read, pit);
+    register_ioport_write(pit->iobase, 4, 1, pit_ioport_write, pit);
+    register_ioport_read(pit->iobase, 3, 1, pit_ioport_read, pit);
+    isa_init_ioport(dev, pit->iobase);
 
-    return pit;
+    return 0;
+}
+
+static ISADeviceInfo pit_info = {
+    .qdev.name     = "isa-pit",
+    .qdev.size     = sizeof(PITState),
+    .qdev.vmsd     = &vmstate_pit,
+    .qdev.reset    = pit_reset,
+    .qdev.no_user  = 1,
+    .init          = pit_initfn,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("irq", PITState, irq,  -1),
+        DEFINE_PROP_HEX32("iobase", PITState, iobase,  -1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void pit_register(void)
+{
+    isa_qdev_register(&pit_info);
 }
+device_init(pit_register)
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 2783ed5..f5ae639 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -67,7 +67,7 @@
 #define FULONG2E_ATI_SLOT        6
 #define FULONG2E_RTL8139_SLOT    7
 
-static PITState *pit;
+static ISADevice *pit;
 
 static struct _loaderparams {
     int ram_size;
@@ -369,7 +369,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     qdev_init_nofail(eeprom);
 
     /* init other devices */
-    pit = pit_init(0x40, isa_reserve_irq(0));
+    pit = pit_init(0x40, 0);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 85eba5a..a100394 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -115,7 +115,7 @@ void mips_jazz_init (ram_addr_t ram_size,
     void* rc4030_opaque;
     int s_rtc, s_dma_dummy;
     NICInfo *nd;
-    PITState *pit;
+    ISADevice *pit;
     DriveInfo *fds[MAX_FD];
     qemu_irq esp_reset, dma_enable;
     qemu_irq *cpu_exit_irq;
@@ -181,7 +181,7 @@ void mips_jazz_init (ram_addr_t ram_size,
     isa_bus_irqs(i8259);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
-    pit = pit_init(0x40, i8259[0]);
+    pit = pit_init(0x40, 0);
     pcspk_init(pit);
 
     /* ISA IO space at 0x90000000 */
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 930c51c..ca6c6d7 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -68,7 +68,7 @@ typedef struct {
     SerialState *uart;
 } MaltaFPGAState;
 
-static PITState *pit;
+static ISADevice *pit;
 
 static struct _loaderparams {
     int ram_size;
@@ -930,7 +930,7 @@ void mips_malta_init (ram_addr_t ram_size,
         qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
         qdev_init_nofail(eeprom);
     }
-    pit = pit_init(0x40, isa_reserve_irq(0));
+    pit = pit_init(0x40, 0);
     cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
     DMA_init(0, cpu_exit_irq);
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index fb34dcf..8feb461 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -30,7 +30,7 @@ static const int ide_iobase[2] = { 0x1f0, 0x170 };
 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
 static const int ide_irq[2] = { 14, 15 };
 
-static PITState *pit; /* PIT i8254 */
+static ISADevice *pit; /* PIT i8254 */
 
 /* i8254 PIT is attached to the IRQ0 at PIC i8259 */
 
@@ -274,7 +274,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
-    pit = pit_init(0x40, i8259[0]);
+    pit = pit_init(0x40, 0);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff --git a/hw/pc.c b/hw/pc.c
index 36641b3..3d7e036 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1104,10 +1104,9 @@ void pc_basic_device_init(qemu_irq *isa_irq,
 {
     int i;
     DriveInfo *fd[MAX_FD];
-    PITState *pit;
     qemu_irq rtc_irq = NULL;
     qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse;
+    ISADevice *i8042, *port92, *vmmouse, *pit;
     qemu_irq *cpu_exit_irq;
 
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -1128,7 +1127,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
 
     qemu_register_boot_set(pc_boot_set, *rtc_state);
 
-    pit = pit_init(0x40, isa_reserve_irq(0));
+    pit = pit_init(0x40, 0);
     pcspk_init(pit);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
diff --git a/hw/pc.h b/hw/pc.h
index 60f8c42..feb8a7a 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -82,14 +82,23 @@ void isa_irq_handler(void *opaque, int n, int level);
 
 #define PIT_FREQ 1193182
 
-typedef struct PITState PITState;
+static inline ISADevice *pit_init(int base, int irq)
+{
+    ISADevice *dev;
+
+    dev = isa_create("isa-pit");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", base);
+    qdev_prop_set_uint32(&dev->qdev, "irq", irq);
+    qdev_init_nofail(&dev->qdev);
+
+    return dev;
+}
 
-PITState *pit_init(int base, qemu_irq irq);
-void pit_set_gate(PITState *pit, int channel, int val);
-int pit_get_gate(PITState *pit, int channel);
-int pit_get_initial_count(PITState *pit, int channel);
-int pit_get_mode(PITState *pit, int channel);
-int pit_get_out(PITState *pit, int channel, int64_t current_time);
+void pit_set_gate(ISADevice *dev, int channel, int val);
+int pit_get_gate(ISADevice *dev, int channel);
+int pit_get_initial_count(ISADevice *dev, int channel);
+int pit_get_mode(ISADevice *dev, int channel);
+int pit_get_out(ISADevice *dev, int channel, int64_t current_time);
 
 void hpet_pit_disable(void);
 void hpet_pit_enable(void);
@@ -159,7 +168,7 @@ void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 extern int no_hpet;
 
 /* pcspk.c */
-void pcspk_init(PITState *);
+void pcspk_init(ISADevice *pit);
 int pcspk_audio_init(qemu_irq *pic);
 
 /* piix_pci.c */
diff --git a/hw/pcspk.c b/hw/pcspk.c
index 26a0ecb..5f02908 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -37,7 +37,7 @@ typedef struct {
     uint8_t sample_buf[PCSPK_BUF_LEN];
     QEMUSoundCard card;
     SWVoiceOut *voice;
-    PITState *pit;
+    ISADevice *pit;
     unsigned int pit_count;
     unsigned int samples;
     unsigned int play_pos;
@@ -137,7 +137,7 @@ static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-void pcspk_init(PITState *pit)
+void pcspk_init(ISADevice *pit)
 {
     PCSpkState *s = &pcspk_state;
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6c1499a..6c9826b 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -82,7 +82,7 @@ static const int ide_irq[2] = { 13, 13 };
 static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
 static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 
-//static PITState *pit;
+//static ISADevice *pit;
 
 /* ISA IO ports bridge */
 #define PPC_IO_BASE 0x80000000
@@ -662,7 +662,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     /* init basic PC hardware */
     pci_vga_init(pci_bus);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
-    //    pit = pit_init(0x40, i8259[0]);
+    //    pit = pit_init(0x40, 0);
     rtc_init(2000, NULL);
 
     if (serial_hds[0])
commit c74b88dffcb2ebfe018e460ac759ae8b1234911d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Feb 13 14:17:00 2011 +0000

    vga-isa: make optional
    
    Ignore failure with vga-isa device creation, but print a warning
    message.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 475484a..60f8c42 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -183,9 +183,15 @@ extern enum vga_retrace_method vga_retrace_method;
 
 static inline int isa_vga_init(void)
 {
-    isa_create_simple("isa-vga");
+    ISADevice *dev;
 
-    return 0;
+    dev = isa_try_create("isa-vga");
+    if (!dev) {
+        fprintf(stderr, "Warning: isa-vga not available\n");
+        return 0;
+    }
+    qdev_init_nofail(&dev->qdev);
+    return 1;
 }
 
 int pci_vga_init(PCIBus *bus);
commit 7435b791ca9c76b11a9dba4beb60656f951432c1
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Feb 13 14:01:05 2011 +0000

    vga-isa: convert to qdev
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 64a3a22..475484a 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -181,7 +181,13 @@ enum vga_retrace_method {
 
 extern enum vga_retrace_method vga_retrace_method;
 
-int isa_vga_init(void);
+static inline int isa_vga_init(void)
+{
+    isa_create_simple("isa-vga");
+
+    return 0;
+}
+
 int pci_vga_init(PCIBus *bus);
 int isa_vga_mm_init(target_phys_addr_t vram_base,
                     target_phys_addr_t ctrl_base, int it_shift);
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 3046054..fde0d56 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -29,16 +29,40 @@
 #include "qemu-timer.h"
 #include "loader.h"
 
-int isa_vga_init(void)
+typedef struct ISAVGAState {
+    ISADevice dev;
+    struct VGACommonState state;
+} ISAVGAState;
+
+static void vga_reset_isa(DeviceState *dev)
 {
-    VGACommonState *s;
+    ISAVGAState *d = container_of(dev, ISAVGAState, dev.qdev);
+    VGACommonState *s = &d->state;
 
-    s = qemu_mallocz(sizeof(*s));
+    vga_common_reset(s);
+}
 
-    vga_common_init(s, VGA_RAM_SIZE);
-    vga_init(s);
-    vmstate_register(NULL, 0, &vmstate_vga_common, s);
+static int vga_initfn(ISADevice *dev)
+{
+    ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
+    VGACommonState *s = &d->state;
+    int vga_io_memory;
 
+    vga_common_init(s, VGA_RAM_SIZE);
+    vga_io_memory = vga_init_io(s);
+    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
+                                 vga_io_memory);
+    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    isa_init_ioport(dev, 0x3c0);
+    isa_init_ioport(dev, 0x3b4);
+    isa_init_ioport(dev, 0x3ba);
+    isa_init_ioport(dev, 0x3da);
+    isa_init_ioport(dev, 0x3c0);
+#ifdef CONFIG_BOCHS_VBE
+    isa_init_ioport(dev, 0x1ce);
+    isa_init_ioport(dev, 0x1cf);
+    isa_init_ioport(dev, 0x1d0);
+#endif /* CONFIG_BOCHS_VBE */
     s->ds = graphic_console_init(s->update, s->invalidate,
                                  s->screen_dump, s->text_update, s);
 
@@ -47,3 +71,18 @@ int isa_vga_init(void)
     rom_add_vga(VGABIOS_FILENAME);
     return 0;
 }
+
+static ISADeviceInfo vga_info = {
+    .qdev.name     = "isa-vga",
+    .qdev.size     = sizeof(ISAVGAState),
+    .qdev.vmsd     = &vmstate_vga_common,
+    .qdev.reset     = vga_reset_isa,
+    .qdev.no_user  = 1,
+    .init          = vga_initfn,
+};
+
+static void vga_register(void)
+{
+    isa_qdev_register(&vga_info);
+}
+device_init(vga_register)
diff --git a/hw/vga.c b/hw/vga.c
index c22b8af..3ef85fb 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2260,12 +2260,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 }
 
 /* used by both ISA and PCI */
-void vga_init(VGACommonState *s)
+int vga_init_io(VGACommonState *s)
 {
-    int vga_io_memory;
-
-    qemu_register_reset(vga_reset, s);
-
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
@@ -2279,7 +2275,6 @@ void vga_init(VGACommonState *s)
     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
-    s->bank_offset = 0;
 
 #ifdef CONFIG_BOCHS_VBE
 #if defined (TARGET_I386)
@@ -2297,8 +2292,19 @@ void vga_init(VGACommonState *s)
 #endif
 #endif /* CONFIG_BOCHS_VBE */
 
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                           DEVICE_LITTLE_ENDIAN);
+    return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
+                                  DEVICE_LITTLE_ENDIAN);
+}
+
+void vga_init(VGACommonState *s)
+{
+    int vga_io_memory;
+
+    qemu_register_reset(vga_reset, s);
+
+    s->bank_offset = 0;
+
+    vga_io_memory = vga_init_io(s);
     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
                                  vga_io_memory);
     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 1067f2c..d2811bd 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -191,6 +191,7 @@ static inline int c6_to_8(int v)
 
 void vga_common_init(VGACommonState *s, int vga_ram_size);
 void vga_init(VGACommonState *s);
+int vga_init_io(VGACommonState *s);
 void vga_common_reset(VGACommonState *s);
 
 void vga_dirty_log_start(VGACommonState *s);
commit 1c9c5fcdfef9d97e5f6d4ce37d41a205a26f0347
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Feb 13 12:31:28 2011 +0000

    applesmc: make optional
    
    Based on patch by David Ahern.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index b21f9d3..c144df1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -196,6 +196,7 @@ hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
 hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 hw-obj-$(CONFIG_DMA) += dma.o
 hw-obj-$(CONFIG_HPET) += hpet.o
+hw-obj-$(CONFIG_APPLESMC) += applesmc.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/Makefile.target b/Makefile.target
index 5a0fd40..220589e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -215,7 +215,7 @@ obj-$(CONFIG_KVM) += ivshmem.o
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o i8259.o pc.o
 obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
-obj-i386-y += vmport.o applesmc.o
+obj-i386-y += vmport.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o kvmclock.o
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 3e0eddf..55589fa 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -20,3 +20,4 @@ CONFIG_NE2000_ISA=y
 CONFIG_PIIX_PCI=y
 CONFIG_SOUND=y
 CONFIG_HPET=y
+CONFIG_APPLESMC=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 1cc1b61..59b7893 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -20,3 +20,4 @@ CONFIG_NE2000_ISA=y
 CONFIG_PIIX_PCI=y
 CONFIG_SOUND=y
 CONFIG_HPET=y
+CONFIG_APPLESMC=y
commit 17801c78fe01ddab7ae9092190d17cc77bd5ef66
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 12 22:25:26 2011 +0000

    fdc: make optional
    
    Ignore failure with fdc device creation.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/fdc.h b/hw/fdc.h
index 3b2fb3b..09f73c6 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -11,7 +11,10 @@ static inline void fdctrl_init_isa(DriveInfo **fds)
 {
     ISADevice *dev;
 
-    dev = isa_create("isa-fdc");
+    dev = isa_try_create("isa-fdc");
+    if (!dev) {
+        return;
+    }
     if (fds[0]) {
         qdev_prop_set_drive_nofail(&dev->qdev, "driveA", fds[0]->bdrv);
     }
commit 63ffb564dca94f8bda01ed6d209784104630a4d2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 16:32:23 2011 +0000

    fdc: refactor device creation
    
    Turn fdc_init_isa into an inline function.
    
    Get floppy geometry directly from the drives.
    
    Don't expose FDCtrl.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index c130cba..9f4779c 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -201,6 +201,8 @@ static void fd_revalidate(FDrive *drv)
 /********************************************************/
 /* Intel 82078 floppy disk controller emulation          */
 
+typedef struct FDCtrl FDCtrl;
+
 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
 static void fdctrl_reset_fifo(FDCtrl *fdctrl);
 static int fdctrl_transfer_handler (void *opaque, int nchan,
@@ -626,12 +628,6 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level)
     }
 }
 
-/* XXX: may change if moved to bdrv */
-FDriveType fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num)
-{
-    return fdctrl->drives[drive_num].drive;
-}
-
 /* Change IRQ state */
 static void fdctrl_reset_irq(FDCtrl *fdctrl)
 {
@@ -1775,23 +1771,8 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
     return 0;
 }
 
-FDCtrl *fdctrl_init_isa(DriveInfo **fds)
-{
-    ISADevice *dev;
-
-    dev = isa_create("isa-fdc");
-    if (fds[0]) {
-        qdev_prop_set_drive_nofail(&dev->qdev, "driveA", fds[0]->bdrv);
-    }
-    if (fds[1]) {
-        qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv);
-    }
-    qdev_init_nofail(&dev->qdev);
-    return &(DO_UPCAST(FDCtrlISABus, busdev, dev)->state);
-}
-
-FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
-                           target_phys_addr_t mmio_base, DriveInfo **fds)
+void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
+                        target_phys_addr_t mmio_base, DriveInfo **fds)
 {
     FDCtrl *fdctrl;
     DeviceState *dev;
@@ -1810,16 +1791,13 @@ FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
     qdev_init_nofail(dev);
     sysbus_connect_irq(&sys->busdev, 0, irq);
     sysbus_mmio_map(&sys->busdev, 0, mmio_base);
-
-    return fdctrl;
 }
 
-FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
-                          DriveInfo **fds, qemu_irq *fdc_tc)
+void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
+                       DriveInfo **fds, qemu_irq *fdc_tc)
 {
     DeviceState *dev;
     FDCtrlSysBus *sys;
-    FDCtrl *fdctrl;
 
     dev = qdev_create(NULL, "SUNW,fdtwo");
     if (fds[0]) {
@@ -1827,12 +1805,9 @@ FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
     }
     qdev_init_nofail(dev);
     sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
-    fdctrl = &sys->state;
     sysbus_connect_irq(&sys->busdev, 0, irq);
     sysbus_mmio_map(&sys->busdev, 0, io_base);
     *fdc_tc = qdev_get_gpio_in(dev, 0);
-
-    return fdctrl;
 }
 
 static int fdctrl_init_common(FDCtrl *fdctrl)
diff --git a/hw/fdc.h b/hw/fdc.h
index 30ac970..3b2fb3b 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -1,18 +1,28 @@
 #ifndef HW_FDC_H
 #define HW_FDC_H
 
+#include "isa.h"
 #include "blockdev.h"
 
 /* fdc.c */
 #define MAX_FD 2
 
-typedef struct FDCtrl FDCtrl;
+static inline void fdctrl_init_isa(DriveInfo **fds)
+{
+    ISADevice *dev;
 
-FDCtrl *fdctrl_init_isa(DriveInfo **fds);
-FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
-                           target_phys_addr_t mmio_base, DriveInfo **fds);
-FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
-                          DriveInfo **fds, qemu_irq *fdc_tc);
-FDriveType fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num);
+    dev = isa_create("isa-fdc");
+    if (fds[0]) {
+        qdev_prop_set_drive_nofail(&dev->qdev, "driveA", fds[0]->bdrv);
+    }
+    if (fds[1]) {
+        qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv);
+    }
+    qdev_init_nofail(&dev->qdev);
+}
 
+void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
+                        target_phys_addr_t mmio_base, DriveInfo **fds);
+void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
+                       DriveInfo **fds, qemu_irq *fdc_tc);
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 4e4e2eb..36641b3 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -334,10 +334,11 @@ static void pc_cmos_init_late(void *opaque)
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device,
                   BusState *idebus0, BusState *idebus1,
-                  FDCtrl *floppy_controller, ISADevice *s)
+                  ISADevice *s)
 {
-    int val, nb;
-    FDriveType fd0, fd1;
+    int val, nb, nb_heads, max_track, last_sect, i;
+    FDriveType fd_type[2];
+    DriveInfo *fd[2];
     static pc_cmos_init_late_arg arg;
 
     /* various important CMOS locations needed by PC/Bochs bios */
@@ -379,19 +380,26 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     }
 
     /* floppy type */
-
-    fd0 = fdctrl_get_drive_type(floppy_controller, 0);
-    fd1 = fdctrl_get_drive_type(floppy_controller, 1);
-
-    val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
+    for (i = 0; i < 2; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+        if (fd[i]) {
+            bdrv_get_floppy_geometry_hint(fd[i]->bdrv, &nb_heads, &max_track,
+                                          &last_sect, FDRIVE_DRV_NONE,
+                                          &fd_type[i]);
+        } else {
+            fd_type[i] = FDRIVE_DRV_NONE;
+        }
+    }
+    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
+        cmos_get_fd_drive_type(fd_type[1]);
     rtc_set_memory(s, 0x10, val);
 
     val = 0;
     nb = 0;
-    if (fd0 < FDRIVE_DRV_NONE) {
+    if (fd_type[0] < FDRIVE_DRV_NONE) {
         nb++;
     }
-    if (fd1 < FDRIVE_DRV_NONE) {
+    if (fd_type[1] < FDRIVE_DRV_NONE) {
         nb++;
     }
     switch (nb) {
@@ -1092,7 +1100,6 @@ static void cpu_request_exit(void *opaque, int irq, int level)
 }
 
 void pc_basic_device_init(qemu_irq *isa_irq,
-                          FDCtrl **floppy_controller,
                           ISADevice **rtc_state)
 {
     int i;
@@ -1153,7 +1160,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     for(i = 0; i < MAX_FD; i++) {
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
-    *floppy_controller = fdctrl_init_isa(fd);
+    fdctrl_init_isa(fd);
 }
 
 void pc_pci_device_init(PCIBus *pci_bus)
diff --git a/hw/pc.h b/hw/pc.h
index 89b43ea..64a3a22 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -129,13 +129,12 @@ void pc_memory_init(ram_addr_t ram_size,
 qemu_irq *pc_allocate_cpu_irq(void);
 void pc_vga_init(PCIBus *pci_bus);
 void pc_basic_device_init(qemu_irq *isa_irq,
-                          FDCtrl **floppy_controller,
                           ISADevice **rtc_state);
 void pc_init_ne2k_isa(NICInfo *nd);
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device,
                   BusState *ide0, BusState *ide1,
-                  FDCtrl *floppy_controller, ISADevice *s);
+                  ISADevice *s);
 void pc_pci_device_init(PCIBus *pci_bus);
 
 typedef void (*cpu_set_smm_t)(int smm, void *arg);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 2918454..b4ca9ec 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -82,7 +82,6 @@ static void pc_init1(ram_addr_t ram_size,
     qemu_irq *smi_irq;
     IsaIrqState *isa_irq_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    FDCtrl *floppy_controller;
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
 
@@ -119,7 +118,7 @@ static void pc_init1(ram_addr_t ram_size,
     pc_vga_init(pci_enabled? pci_bus: NULL);
 
     /* init basic PC hardware */
-    pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);
+    pc_basic_device_init(isa_irq, &rtc_state);
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
@@ -156,7 +155,7 @@ static void pc_init1(ram_addr_t ram_size,
     audio_init(isa_irq, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                 idebus[0], idebus[1], floppy_controller, rtc_state);
+                 idebus[0], idebus[1], rtc_state);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
commit d288c7ba7beb7975fe4bc15b0b14b9fd14da0a03
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 12 21:23:12 2011 +0000

    fdc: use FDriveType for floppy drive type
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index 5874a66..c130cba 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -627,7 +627,7 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level)
 }
 
 /* XXX: may change if moved to bdrv */
-int fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num)
+FDriveType fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num)
 {
     return fdctrl->drives[drive_num].drive;
 }
diff --git a/hw/fdc.h b/hw/fdc.h
index 242730a..30ac970 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -1,6 +1,8 @@
 #ifndef HW_FDC_H
 #define HW_FDC_H
 
+#include "blockdev.h"
+
 /* fdc.c */
 #define MAX_FD 2
 
@@ -11,6 +13,6 @@ FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
                            target_phys_addr_t mmio_base, DriveInfo **fds);
 FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
                           DriveInfo **fds, qemu_irq *fdc_tc);
-int fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num);
+FDriveType fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num);
 
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 56bf1d6..4e4e2eb 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -192,23 +192,24 @@ static void pic_irq_request(void *opaque, int irq, int level)
 
 #define REG_EQUIPMENT_BYTE          0x14
 
-static int cmos_get_fd_drive_type(int fd0)
+static int cmos_get_fd_drive_type(FDriveType fd0)
 {
     int val;
 
     switch (fd0) {
-    case 0:
+    case FDRIVE_DRV_144:
         /* 1.44 Mb 3"5 drive */
         val = 4;
         break;
-    case 1:
+    case FDRIVE_DRV_288:
         /* 2.88 Mb 3"5 drive */
         val = 5;
         break;
-    case 2:
+    case FDRIVE_DRV_120:
         /* 1.2 Mb 5"5 drive */
         val = 2;
         break;
+    case FDRIVE_DRV_NONE:
     default:
         val = 0;
         break;
@@ -335,8 +336,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   BusState *idebus0, BusState *idebus1,
                   FDCtrl *floppy_controller, ISADevice *s)
 {
-    int val;
-    int fd0, fd1, nb;
+    int val, nb;
+    FDriveType fd0, fd1;
     static pc_cmos_init_late_arg arg;
 
     /* various important CMOS locations needed by PC/Bochs bios */
@@ -387,10 +388,12 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 
     val = 0;
     nb = 0;
-    if (fd0 < 3)
+    if (fd0 < FDRIVE_DRV_NONE) {
         nb++;
-    if (fd1 < 3)
+    }
+    if (fd1 < FDRIVE_DRV_NONE) {
         nb++;
+    }
     switch (nb) {
     case 0:
         break;
commit 5bbdbb4676d17e782ae83055bac58e0751b25e4b
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 12 20:43:32 2011 +0000

    fdc: move floppy geometry guessing to block.c
    
    Other geometry guessing functions already reside in block.c.
    
    Remove some unused or debugging only fields.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block.c b/block.c
index b476479..f7d91a2 100644
--- a/block.c
+++ b/block.c
@@ -1319,6 +1319,109 @@ void bdrv_get_geometry_hint(BlockDriverState *bs,
     *psecs = bs->secs;
 }
 
+/* Recognize floppy formats */
+typedef struct FDFormat {
+    FDriveType drive;
+    uint8_t last_sect;
+    uint8_t max_track;
+    uint8_t max_head;
+} FDFormat;
+
+static const FDFormat fd_formats[] = {
+    /* First entry is default format */
+    /* 1.44 MB 3"1/2 floppy disks */
+    { FDRIVE_DRV_144, 18, 80, 1, },
+    { FDRIVE_DRV_144, 20, 80, 1, },
+    { FDRIVE_DRV_144, 21, 80, 1, },
+    { FDRIVE_DRV_144, 21, 82, 1, },
+    { FDRIVE_DRV_144, 21, 83, 1, },
+    { FDRIVE_DRV_144, 22, 80, 1, },
+    { FDRIVE_DRV_144, 23, 80, 1, },
+    { FDRIVE_DRV_144, 24, 80, 1, },
+    /* 2.88 MB 3"1/2 floppy disks */
+    { FDRIVE_DRV_288, 36, 80, 1, },
+    { FDRIVE_DRV_288, 39, 80, 1, },
+    { FDRIVE_DRV_288, 40, 80, 1, },
+    { FDRIVE_DRV_288, 44, 80, 1, },
+    { FDRIVE_DRV_288, 48, 80, 1, },
+    /* 720 kB 3"1/2 floppy disks */
+    { FDRIVE_DRV_144,  9, 80, 1, },
+    { FDRIVE_DRV_144, 10, 80, 1, },
+    { FDRIVE_DRV_144, 10, 82, 1, },
+    { FDRIVE_DRV_144, 10, 83, 1, },
+    { FDRIVE_DRV_144, 13, 80, 1, },
+    { FDRIVE_DRV_144, 14, 80, 1, },
+    /* 1.2 MB 5"1/4 floppy disks */
+    { FDRIVE_DRV_120, 15, 80, 1, },
+    { FDRIVE_DRV_120, 18, 80, 1, },
+    { FDRIVE_DRV_120, 18, 82, 1, },
+    { FDRIVE_DRV_120, 18, 83, 1, },
+    { FDRIVE_DRV_120, 20, 80, 1, },
+    /* 720 kB 5"1/4 floppy disks */
+    { FDRIVE_DRV_120,  9, 80, 1, },
+    { FDRIVE_DRV_120, 11, 80, 1, },
+    /* 360 kB 5"1/4 floppy disks */
+    { FDRIVE_DRV_120,  9, 40, 1, },
+    { FDRIVE_DRV_120,  9, 40, 0, },
+    { FDRIVE_DRV_120, 10, 41, 1, },
+    { FDRIVE_DRV_120, 10, 42, 1, },
+    /* 320 kB 5"1/4 floppy disks */
+    { FDRIVE_DRV_120,  8, 40, 1, },
+    { FDRIVE_DRV_120,  8, 40, 0, },
+    /* 360 kB must match 5"1/4 better than 3"1/2... */
+    { FDRIVE_DRV_144,  9, 80, 0, },
+    /* end */
+    { FDRIVE_DRV_NONE, -1, -1, 0, },
+};
+
+void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
+                                   int *max_track, int *last_sect,
+                                   FDriveType drive_in, FDriveType *drive)
+{
+    const FDFormat *parse;
+    uint64_t nb_sectors, size;
+    int i, first_match, match;
+
+    bdrv_get_geometry_hint(bs, nb_heads, max_track, last_sect);
+    if (*nb_heads != 0 && *max_track != 0 && *last_sect != 0) {
+        /* User defined disk */
+    } else {
+        bdrv_get_geometry(bs, &nb_sectors);
+        match = -1;
+        first_match = -1;
+        for (i = 0; ; i++) {
+            parse = &fd_formats[i];
+            if (parse->drive == FDRIVE_DRV_NONE) {
+                break;
+            }
+            if (drive_in == parse->drive ||
+                drive_in == FDRIVE_DRV_NONE) {
+                size = (parse->max_head + 1) * parse->max_track *
+                    parse->last_sect;
+                if (nb_sectors == size) {
+                    match = i;
+                    break;
+                }
+                if (first_match == -1) {
+                    first_match = i;
+                }
+            }
+        }
+        if (match == -1) {
+            if (first_match == -1) {
+                match = 1;
+            } else {
+                match = first_match;
+            }
+            parse = &fd_formats[match];
+        }
+        *nb_heads = parse->max_head + 1;
+        *max_track = parse->max_track;
+        *last_sect = parse->last_sect;
+        *drive = parse->drive;
+    }
+}
+
 int bdrv_get_type_hint(BlockDriverState *bs)
 {
     return bs->type;
diff --git a/block.h b/block.h
index 19f4768..5d78fc0 100644
--- a/block.h
+++ b/block.h
@@ -166,6 +166,16 @@ void bdrv_set_type_hint(BlockDriverState *bs, int type);
 void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
 void bdrv_get_geometry_hint(BlockDriverState *bs,
                             int *pcyls, int *pheads, int *psecs);
+typedef enum FDriveType {
+    FDRIVE_DRV_144  = 0x00,   /* 1.44 MB 3"5 drive      */
+    FDRIVE_DRV_288  = 0x01,   /* 2.88 MB 3"5 drive      */
+    FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */
+    FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
+} FDriveType;
+
+void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
+                                   int *max_track, int *last_sect,
+                                   FDriveType drive_in, FDriveType *drive);
 int bdrv_get_type_hint(BlockDriverState *bs);
 int bdrv_get_translation_hint(BlockDriverState *bs);
 void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
diff --git a/hw/fdc.c b/hw/fdc.c
index 4bbcc47..5874a66 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -63,21 +63,6 @@
 #define FD_RESET_SENSEI_COUNT  4   /* Number of sense interrupts on RESET */
 
 /* Floppy disk drive emulation */
-typedef enum FDiskType {
-    FDRIVE_DISK_288   = 0x01, /* 2.88 MB disk           */
-    FDRIVE_DISK_144   = 0x02, /* 1.44 MB disk           */
-    FDRIVE_DISK_720   = 0x03, /* 720 kB disk            */
-    FDRIVE_DISK_USER  = 0x04, /* User defined geometry  */
-    FDRIVE_DISK_NONE  = 0x05, /* No disk                */
-} FDiskType;
-
-typedef enum FDriveType {
-    FDRIVE_DRV_144  = 0x00,   /* 1.44 MB 3"5 drive      */
-    FDRIVE_DRV_288  = 0x01,   /* 2.88 MB 3"5 drive      */
-    FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */
-    FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
-} FDriveType;
-
 typedef enum FDiskFlags {
     FDISK_DBL_SIDES  = 0x01,
 } FDiskFlags;
@@ -178,111 +163,23 @@ static void fd_recalibrate(FDrive *drv)
     drv->sect = 1;
 }
 
-/* Recognize floppy formats */
-typedef struct FDFormat {
-    FDriveType drive;
-    FDiskType  disk;
-    uint8_t last_sect;
-    uint8_t max_track;
-    uint8_t max_head;
-    const char *str;
-} FDFormat;
-
-static const FDFormat fd_formats[] = {
-    /* First entry is default format */
-    /* 1.44 MB 3"1/2 floppy disks */
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1,  "1.6 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
-    /* 2.88 MB 3"1/2 floppy disks */
-    { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
-    { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
-    { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1,  "3.2 MB 3\"1/2", },
-    { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
-    { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
-    /* 720 kB 3"1/2 floppy disks */
-    { FDRIVE_DRV_144, FDRIVE_DISK_720,  9, 80, 1,  "720 kB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1,  "800 kB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1,  "820 kB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1,  "830 kB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
-    { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
-    /* 1.2 MB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1,  "1.2 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1,  "1.6 MB 5\"1/4", },
-    /* 720 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 80, 1,  "720 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1,  "880 kB 5\"1/4", },
-    /* 360 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 40, 1,  "360 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 40, 0,  "180 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1,  "410 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1,  "420 kB 5\"1/4", },
-    /* 320 kB 5"1/4 floppy disks */
-    { FDRIVE_DRV_120, FDRIVE_DISK_288,  8, 40, 1,  "320 kB 5\"1/4", },
-    { FDRIVE_DRV_120, FDRIVE_DISK_288,  8, 40, 0,  "160 kB 5\"1/4", },
-    /* 360 kB must match 5"1/4 better than 3"1/2... */
-    { FDRIVE_DRV_144, FDRIVE_DISK_720,  9, 80, 0,  "360 kB 3\"1/2", },
-    /* end */
-    { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
-};
-
 /* Revalidate a disk drive after a disk change */
 static void fd_revalidate(FDrive *drv)
 {
-    const FDFormat *parse;
-    uint64_t nb_sectors, size;
-    int i, first_match, match;
     int nb_heads, max_track, last_sect, ro;
+    FDriveType drive;
 
     FLOPPY_DPRINTF("revalidate\n");
     if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
         ro = bdrv_is_read_only(drv->bs);
-        bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
+        bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
+                                      &last_sect, drv->drive, &drive);
         if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
             FLOPPY_DPRINTF("User defined disk (%d %d %d)",
                            nb_heads - 1, max_track, last_sect);
         } else {
-            bdrv_get_geometry(drv->bs, &nb_sectors);
-            match = -1;
-            first_match = -1;
-            for (i = 0;; i++) {
-                parse = &fd_formats[i];
-                if (parse->drive == FDRIVE_DRV_NONE)
-                    break;
-                if (drv->drive == parse->drive ||
-                    drv->drive == FDRIVE_DRV_NONE) {
-                    size = (parse->max_head + 1) * parse->max_track *
-                        parse->last_sect;
-                    if (nb_sectors == size) {
-                        match = i;
-                        break;
-                    }
-                    if (first_match == -1)
-                        first_match = i;
-                }
-            }
-            if (match == -1) {
-                if (first_match == -1)
-                    match = 1;
-                else
-                    match = first_match;
-                parse = &fd_formats[match];
-            }
-            nb_heads = parse->max_head + 1;
-            max_track = parse->max_track;
-            last_sect = parse->last_sect;
-            drv->drive = parse->drive;
-            FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
-                           nb_heads, max_track, last_sect, ro ? "ro" : "rw");
+            FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
+                           max_track, last_sect, ro ? "ro" : "rw");
         }
         if (nb_heads == 1) {
             drv->flags &= ~FDISK_DBL_SIDES;
@@ -292,6 +189,7 @@ static void fd_revalidate(FDrive *drv)
         drv->max_track = max_track;
         drv->last_sect = last_sect;
         drv->ro = ro;
+        drv->drive = drive;
     } else {
         FLOPPY_DPRINTF("No disk in drive\n");
         drv->last_sect = 0;
commit 9b13ef9f4c5be62bf405ab4291e090631089707f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 21:30:42 2011 +0000

    serial: make optional
    
    Ignore failure with serial device creation.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 09f63f0..89b43ea 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -21,7 +21,10 @@ static inline bool serial_isa_init(int index, CharDriverState *chr)
 {
     ISADevice *dev;
 
-    dev = isa_create("isa-serial");
+    dev = isa_try_create("isa-serial");
+    if (!dev) {
+        return false;
+    }
     qdev_prop_set_uint32(&dev->qdev, "index", index);
     qdev_prop_set_chr(&dev->qdev, "chardev", chr);
     if (qdev_init(&dev->qdev) < 0) {
commit e22cf21efdc5f25fb9ba136cba7acb71aa379ea7
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 19:37:40 2011 +0000

    serial: refactor device creation
    
    Turn serial_init into an inline function.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 50d9943..09f63f0 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -17,7 +17,19 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
                              qemu_irq irq, int baudbase,
                              CharDriverState *chr, int ioregister,
                              int be);
-SerialState *serial_isa_init(int index, CharDriverState *chr);
+static inline bool serial_isa_init(int index, CharDriverState *chr)
+{
+    ISADevice *dev;
+
+    dev = isa_create("isa-serial");
+    qdev_prop_set_uint32(&dev->qdev, "index", index);
+    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
+    if (qdev_init(&dev->qdev) < 0) {
+        return false;
+    }
+    return true;
+}
+
 void serial_set_frequency(SerialState *s, uint32_t frequency);
 
 /* parallel.c */
diff --git a/hw/serial.c b/hw/serial.c
index 2c4af61..879237f 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -782,18 +782,6 @@ static int serial_isa_initfn(ISADevice *dev)
     return 0;
 }
 
-SerialState *serial_isa_init(int index, CharDriverState *chr)
-{
-    ISADevice *dev;
-
-    dev = isa_create("isa-serial");
-    qdev_prop_set_uint32(&dev->qdev, "index", index);
-    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
-    if (qdev_init(&dev->qdev) < 0)
-        return NULL;
-    return &DO_UPCAST(ISASerialState, dev, dev)->state;
-}
-
 static const VMStateDescription vmstate_isa_serial = {
     .name = "serial",
     .version_id = 3,
commit cd1b8a8b0d5951fb3a575a13bfd3aa3f7018ef1f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 15:44:45 2011 +0000

    ne2000_isa: make optional
    
    Ignore failure with ne2000_isa device creation.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index abdf307..50d9943 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -5,6 +5,7 @@
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
+#include "net.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -176,17 +177,21 @@ void pci_cirrus_vga_init(PCIBus *bus);
 void isa_cirrus_vga_init(void);
 
 /* ne2000.c */
-static inline void isa_ne2000_init(int base, int irq, NICInfo *nd)
+static inline bool isa_ne2000_init(int base, int irq, NICInfo *nd)
 {
     ISADevice *dev;
 
     qemu_check_nic_model(nd, "ne2k_isa");
 
-    dev = isa_create("ne2k_isa");
+    dev = isa_try_create("ne2k_isa");
+    if (!dev) {
+        return false;
+    }
     qdev_prop_set_uint32(&dev->qdev, "iobase", base);
     qdev_prop_set_uint32(&dev->qdev, "irq",    irq);
     qdev_set_nic_properties(&dev->qdev, nd);
     qdev_init_nofail(&dev->qdev);
+    return true;
 }
 
 /* e820 types */
commit 60a14ad31e3629c13816d5060cb30d73985171e9
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 15:39:57 2011 +0000

    ne2000_isa: refactor device creation
    
    Turn isa_ne2000_init into an inline function.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c
index 3ff0d89..e41dbba 100644
--- a/hw/ne2000-isa.c
+++ b/hw/ne2000-isa.c
@@ -92,19 +92,6 @@ static int isa_ne2000_initfn(ISADevice *dev)
     return 0;
 }
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd)
-{
-    ISADevice *dev;
-
-    qemu_check_nic_model(nd, "ne2k_isa");
-
-    dev = isa_create("ne2k_isa");
-    qdev_prop_set_uint32(&dev->qdev, "iobase", base);
-    qdev_prop_set_uint32(&dev->qdev, "irq",    irq);
-    qdev_set_nic_properties(&dev->qdev, nd);
-    qdev_init_nofail(&dev->qdev);
-}
-
 static ISADeviceInfo ne2000_isa_info = {
     .qdev.name  = "ne2k_isa",
     .qdev.size  = sizeof(ISANE2000State),
diff --git a/hw/pc.h b/hw/pc.h
index f823b7d..abdf307 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,8 +176,18 @@ void pci_cirrus_vga_init(PCIBus *bus);
 void isa_cirrus_vga_init(void);
 
 /* ne2000.c */
+static inline void isa_ne2000_init(int base, int irq, NICInfo *nd)
+{
+    ISADevice *dev;
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd);
+    qemu_check_nic_model(nd, "ne2k_isa");
+
+    dev = isa_create("ne2k_isa");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", base);
+    qdev_prop_set_uint32(&dev->qdev, "irq",    irq);
+    qdev_set_nic_properties(&dev->qdev, nd);
+    qdev_init_nofail(&dev->qdev);
+}
 
 /* e820 types */
 #define E820_RAM        1
commit 7353153891a9bbdbaa1672c37208effb5a09d715
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 14:56:53 2011 +0000

    parallel: make optional
    
    Ignore failure with parallel device creation.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 443ba34..f823b7d 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -24,7 +24,10 @@ static inline bool parallel_init(int index, CharDriverState *chr)
 {
     ISADevice *dev;
 
-    dev = isa_create("isa-parallel");
+    dev = isa_try_create("isa-parallel");
+    if (!dev) {
+        return false;
+    }
     qdev_prop_set_uint32(&dev->qdev, "index", index);
     qdev_prop_set_chr(&dev->qdev, "chardev", chr);
     if (qdev_init(&dev->qdev) < 0) {
commit defdb20e1a8ac3a7200aaf190d7fb20a5ac8bcea
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 14:51:57 2011 +0000

    parallel: refactor device creation
    
    Turn parallel_init into an inline function.
    
    Don't expose ParallelState.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/parallel.c b/hw/parallel.c
index ce311aa..cc853a5 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -64,7 +64,7 @@
 
 #define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
 
-struct ParallelState {
+typedef struct ParallelState {
     uint8_t dataw;
     uint8_t datar;
     uint8_t status;
@@ -77,7 +77,7 @@ struct ParallelState {
     uint32_t last_read_offset; /* For debugging */
     /* Memory-mapped interface */
     int it_shift;
-};
+} ParallelState;
 
 typedef struct ISAParallelState {
     ISADevice dev;
@@ -500,18 +500,6 @@ static int parallel_isa_initfn(ISADevice *dev)
     return 0;
 }
 
-ParallelState *parallel_init(int index, CharDriverState *chr)
-{
-    ISADevice *dev;
-
-    dev = isa_create("isa-parallel");
-    qdev_prop_set_uint32(&dev->qdev, "index", index);
-    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
-    if (qdev_init(&dev->qdev) < 0)
-        return NULL;
-    return &DO_UPCAST(ISAParallelState, dev, dev)->state;
-}
-
 /* Memory mapped interface */
 static uint32_t parallel_mm_readb (void *opaque, target_phys_addr_t addr)
 {
@@ -571,7 +559,8 @@ static CPUWriteMemoryFunc * const parallel_mm_write_sw[] = {
 };
 
 /* If fd is zero, it means that the parallel device uses the console */
-ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, CharDriverState *chr)
+bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+                      CharDriverState *chr)
 {
     ParallelState *s;
     int io_sw;
@@ -585,7 +574,7 @@ ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq
     io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw,
                                    s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 8 << it_shift, io_sw);
-    return s;
+    return true;
 }
 
 static ISADeviceInfo parallel_isa_info = {
diff --git a/hw/pc.h b/hw/pc.h
index d5d2f42..443ba34 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -20,10 +20,21 @@ SerialState *serial_isa_init(int index, CharDriverState *chr);
 void serial_set_frequency(SerialState *s, uint32_t frequency);
 
 /* parallel.c */
+static inline bool parallel_init(int index, CharDriverState *chr)
+{
+    ISADevice *dev;
+
+    dev = isa_create("isa-parallel");
+    qdev_prop_set_uint32(&dev->qdev, "index", index);
+    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
+    if (qdev_init(&dev->qdev) < 0) {
+        return false;
+    }
+    return true;
+}
 
-typedef struct ParallelState ParallelState;
-ParallelState *parallel_init(int index, CharDriverState *chr);
-ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, CharDriverState *chr);
+bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
+                      CharDriverState *chr);
 
 /* i8259.c */
 
commit e14da0af640e4255b15d81907a93a2637e14e478
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Thu Feb 17 01:27:19 2011 -0200

    Fix vmport segfault (v2)
    
    Fix regression caused by qdev conversion.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/vmport.c b/hw/vmport.c
index 292d78f..19010e4 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -43,15 +43,15 @@ typedef struct _VMPortState
     void *opaque[VMPORT_ENTRIES];
 } VMPortState;
 
-static VMPortState port_state;
+static VMPortState *port_state;
 
 void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque)
 {
     if (command >= VMPORT_ENTRIES)
         return;
 
-    port_state.func[command] = func;
-    port_state.opaque[command] = opaque;
+    port_state->func[command] = func;
+    port_state->opaque[command] = opaque;
 }
 
 static uint32_t vmport_ioport_read(void *opaque, uint32_t addr)
@@ -125,9 +125,10 @@ static int vmport_initfn(ISADevice *dev)
 {
     VMPortState *s = DO_UPCAST(VMPortState, dev, dev);
 
-    register_ioport_read(0x5658, 1, 4, vmport_ioport_read, &s);
-    register_ioport_write(0x5658, 1, 4, vmport_ioport_write, &s);
+    register_ioport_read(0x5658, 1, 4, vmport_ioport_read, s);
+    register_ioport_write(0x5658, 1, 4, vmport_ioport_write, s);
     isa_init_ioport(dev, 0x5658);
+    port_state = s;
     /* Register some generic port commands */
     vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL);
     vmport_register(VMPORT_CMD_GETRAMSIZE, vmport_cmd_ram_size, NULL);
commit 80f5ce758ac277e76c016dd7c0b246e40d4fca2d
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Sun Feb 13 23:37:35 2011 +0100

    linux-user: correct core dump format
    
    This patch allows to really use the core dumped by qemu with guest
    architecture tools.
    
    - it adds a missing bswap_phdr() for the program headers
      of memory regions.
    
      "objdump -x" sample:
    
    BEFORE:
    
    0x1000000 off    0x00200000 vaddr 0x00000400 paddr 0x00000000 align 2**21
             filesz 0x00000000 memsz 0x00100000 flags ---
    0x1000000 off    0x00200000 vaddr 0x00100400 paddr 0x00000000 align 2**21
             filesz 0x00000000 memsz 0x00080000 flags --- 6000000
    
    AFTER:
    
        LOAD off    0x00002000 vaddr 0x00040000 paddr 0x00000000 align 2**13
             filesz 0x00000000 memsz 0x00001000 flags ---
        LOAD off    0x00002000 vaddr 0x00041000 paddr 0x00000000 align 2**13
             filesz 0x00000000 memsz 0x00000800 flags rw-
    
    - it doesn't pad the note size to sizeof(int32_t).
      On m68k the NT_PRSTATUS note size is 154 and
      must not be rounded up to 156, because this value is checked by
      objdump and gdb.
    
      "gdb" symptoms:
    
          "warning: Couldn't find general-purpose registers in core file."
    
      "objdump -x" sample:
    
    BEFORE:
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 note0         000001c4  00000000  00000000  000003b4  2**0
                      CONTENTS, READONLY
      1 .auxv         00000070  00000000  00000000  00000508  2**2
                      CONTENTS
      2 proc1         00100000  00000400  00000000  00200000  2**10
                      READONLY
    
    AFTER:
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 note0         000001c4  00000000  00000000  000003b4  2**0
                      CONTENTS, READONLY
      1 .reg/19022    00000050  00000000  00000000  0000040e  2**2
                      CONTENTS
      2 .reg          00000050  00000000  00000000  0000040e  2**2
                      CONTENTS
      3 .auxv         00000070  00000000  00000000  00000508  2**2
                      CONTENTS
      4 load1         00000000  00040000  00000000  00002000  2**13
                      ALLOC, READONLY
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2de83e4..fe5410e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -103,13 +103,13 @@ enum {
 
 typedef target_ulong    target_elf_greg_t;
 #ifdef USE_UID16
-typedef uint16_t        target_uid_t;
-typedef uint16_t        target_gid_t;
+typedef target_ushort   target_uid_t;
+typedef target_ushort   target_gid_t;
 #else
-typedef uint32_t        target_uid_t;
-typedef uint32_t        target_gid_t;
+typedef target_uint     target_uid_t;
+typedef target_uint     target_gid_t;
 #endif
-typedef int32_t         target_pid_t;
+typedef target_int      target_pid_t;
 
 #ifdef TARGET_I386
 
@@ -1761,19 +1761,20 @@ struct memelfnote {
     size_t     namesz_rounded;
     int        type;
     size_t     datasz;
+    size_t     datasz_rounded;
     void       *data;
     size_t     notesz;
 };
 
 struct target_elf_siginfo {
-    int  si_signo; /* signal number */
-    int  si_code;  /* extra code */
-    int  si_errno; /* errno */
+    target_int  si_signo; /* signal number */
+    target_int  si_code;  /* extra code */
+    target_int  si_errno; /* errno */
 };
 
 struct target_elf_prstatus {
     struct target_elf_siginfo pr_info;      /* Info associated with signal */
-    short              pr_cursig;    /* Current signal */
+    target_short       pr_cursig;    /* Current signal */
     target_ulong       pr_sigpend;   /* XXX */
     target_ulong       pr_sighold;   /* XXX */
     target_pid_t       pr_pid;
@@ -1785,7 +1786,7 @@ struct target_elf_prstatus {
     struct target_timeval pr_cutime; /* XXX Cumulative user time */
     struct target_timeval pr_cstime; /* XXX Cumulative system time */
     target_elf_gregset_t      pr_reg;       /* GP registers */
-    int                pr_fpvalid;   /* XXX */
+    target_int         pr_fpvalid;   /* XXX */
 };
 
 #define ELF_PRARGSZ     (80) /* Number of chars for args */
@@ -2036,7 +2037,9 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
     note->namesz = namesz;
     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
     note->type = type;
-    note->datasz = roundup(sz, sizeof (int32_t));;
+    note->datasz = sz;
+    note->datasz_rounded = roundup(sz, sizeof (int32_t));
+
     note->data = data;
 
     /*
@@ -2044,7 +2047,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
      * ELF document.
      */
     note->notesz = sizeof (struct elf_note) +
-        note->namesz_rounded + note->datasz;
+        note->namesz_rounded + note->datasz_rounded;
 }
 
 static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
@@ -2264,7 +2267,7 @@ static int write_note(struct memelfnote *men, int fd)
         return (-1);
     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
         return (-1);
-    if (dump_write(fd, men->data, men->datasz) != 0)
+    if (dump_write(fd, men->data, men->datasz_rounded) != 0)
         return (-1);
 
     return (0);
@@ -2480,7 +2483,7 @@ static int elf_core_dump(int signr, const CPUState *env)
      * ELF specification wants data to start at page boundary so
      * we align it here.
      */
-    offset = roundup(offset, ELF_EXEC_PAGESIZE);
+    data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
     /*
      * Write program headers for memory regions mapped in
@@ -2503,6 +2506,7 @@ static int elf_core_dump(int signr, const CPUState *env)
             phdr.p_flags |= PF_X;
         phdr.p_align = ELF_EXEC_PAGESIZE;
 
+        bswap_phdr(&phdr, 1);
         dump_write(fd, &phdr, sizeof (phdr));
     }
 
@@ -2514,8 +2518,6 @@ static int elf_core_dump(int signr, const CPUState *env)
         goto out;
 
     /* align data to page boundary */
-    data_offset = lseek(fd, 0, SEEK_CUR);
-    data_offset = TARGET_PAGE_ALIGN(data_offset);
     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
         goto out;
 
commit c2e3dee6e03527baf8698698cce76b1a3174969a
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Sun Feb 13 23:37:34 2011 +0100

    linux-user: Define target alignment size
    
    Datatype alignment can be found using following application:
    
    int main(void)
    {
    	printf("alignof(short) %ld\n", __alignof__(short));
    	printf("alignof(int) %ld\n", __alignof__(int));
    	printf("alignof(long) %ld\n", __alignof__(long));
    	printf("alignof(long long) %ld\n", __alignof__(long long));
    }
    
    This patch includes following alignments:
    
    i386
    
       alignof(short) 2
       alignof(int) 4
       alignof(long) 4
       alignof(long long) 8
    
     x86_64
    
       alignof(short) 2
       alignof(int) 4
       alignof(long) 8
       alignof(long long) 8
    
     arm
    
       alignof(short) 2
       alignof(int) 4
       alignof(long) 4
       alignof(long long) 4
    
     m68k (680x0)
    
       alignof(short) 2
       alignof(int) 2
       alignof(long) 2
       alignof(long long) 2
    
     mips
    
       alignof(short) 2
       alignof(int) 4
       alignof(long) 4
       alignof(long long) 8
    
     ppc
    
       alignof(short) 2
       alignof(int) 4
       alignof(long) 4
       alignof(long long) 8
    
    for other targets, use by default (2,4,4,8).
    
    Please, update for your favorite target...
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/configure b/configure
index cb72ced..fe00036 100755
--- a/configure
+++ b/configure
@@ -2962,6 +2962,10 @@ target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
 echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
 gdb_xml_files=""
+target_short_alignment=2
+target_int_alignment=4
+target_long_alignment=4
+target_llong_alignment=8
 
 TARGET_ARCH="$target_arch2"
 TARGET_BASE_ARCH=""
@@ -2974,9 +2978,11 @@ case "$target_arch2" in
   x86_64)
     TARGET_BASE_ARCH=i386
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   alpha)
     target_phys_bits=64
+    target_long_alignment=8
     target_nptl="yes"
   ;;
   arm|armeb)
@@ -2985,6 +2991,7 @@ case "$target_arch2" in
     target_nptl="yes"
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
     target_phys_bits=32
+    target_llong_alignment=4
   ;;
   cris)
     target_nptl="yes"
@@ -2994,6 +3001,9 @@ case "$target_arch2" in
     bflt="yes"
     gdb_xml_files="cf-core.xml cf-fp.xml"
     target_phys_bits=32
+    target_int_alignment=2
+    target_long_alignment=2
+    target_llong_alignment=2
   ;;
   microblaze)
     bflt="yes"
@@ -3017,6 +3027,7 @@ case "$target_arch2" in
     TARGET_BASE_ARCH=mips
     echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
@@ -3035,6 +3046,7 @@ case "$target_arch2" in
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   ppc64abi32)
     TARGET_ARCH=ppc64
@@ -3056,6 +3068,7 @@ case "$target_arch2" in
   sparc64)
     TARGET_BASE_ARCH=sparc
     target_phys_bits=64
+    target_long_alignment=8
   ;;
   sparc32plus)
     TARGET_ARCH=sparc64
@@ -3072,6 +3085,10 @@ case "$target_arch2" in
     exit 1
   ;;
 esac
+echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
+echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
+echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
+echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
 echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
 target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`"
 echo "TARGET_$target_arch_name=y" >> $config_target_mak
diff --git a/cpu-defs.h b/cpu-defs.h
index db809ed..2b59fa6 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -37,16 +37,22 @@
 
 #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
 
+typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
+typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
 /* target_ulong is the type of a virtual address */
 #if TARGET_LONG_SIZE == 4
-typedef int32_t target_long;
-typedef uint32_t target_ulong;
+typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
 #define TARGET_FMT_lx "%08x"
 #define TARGET_FMT_ld "%d"
 #define TARGET_FMT_lu "%u"
 #elif TARGET_LONG_SIZE == 8
-typedef int64_t target_long;
-typedef uint64_t target_ulong;
+typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
 #define TARGET_FMT_lx "%016" PRIx64
 #define TARGET_FMT_ld "%" PRId64
 #define TARGET_FMT_lu "%" PRIu64
commit 3b6edd1611e25099a1df20771ce3f88939a0e93a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 15 18:35:05 2011 +0000

    linux-user: Support the epoll syscalls
    
    Support the epoll family of syscalls: epoll_create(), epoll_create1(),
    epoll_ctl(), epoll_wait() and epoll_pwait(). Note that epoll_create1()
    and epoll_pwait() are later additions, so we have to test separately
    in configure for their presence.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/configure b/configure
index a3f5345..cb72ced 100755
--- a/configure
+++ b/configure
@@ -2142,6 +2142,51 @@ if compile_prog "" "" ; then
   dup3=yes
 fi
 
+# check for epoll support
+epoll=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+    epoll_create(0);
+    return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+  epoll=yes
+fi
+
+# epoll_create1 and epoll_pwait are later additions
+# so we must check separately for their presence
+epoll_create1=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+    epoll_create1(0);
+    return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+  epoll_create1=yes
+fi
+
+epoll_pwait=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+    epoll_pwait(0, 0, 0, 0, 0);
+    return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+  epoll_pwait=yes
+fi
+
 # Check if tools are available to build documentation.
 if test "$docs" != "no" ; then
   if has makeinfo && has pod2man; then
@@ -2674,6 +2719,15 @@ fi
 if test "$dup3" = "yes" ; then
   echo "CONFIG_DUP3=y" >> $config_host_mak
 fi
+if test "$epoll" = "yes" ; then
+  echo "CONFIG_EPOLL=y" >> $config_host_mak
+fi
+if test "$epoll_create1" = "yes" ; then
+  echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak
+fi
+if test "$epoll_pwait" = "yes" ; then
+  echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak
+fi
 if test "$inotify" = "yes" ; then
   echo "CONFIG_INOTIFY=y" >> $config_host_mak
 fi
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4412a9b..cf8a4c3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -66,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #ifdef CONFIG_EVENTFD
 #include <sys/eventfd.h>
 #endif
+#ifdef CONFIG_EPOLL
+#include <sys/epoll.h>
+#endif
 
 #define termios host_termios
 #define winsize host_winsize
@@ -7612,6 +7615,110 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
 #endif
+#if defined(CONFIG_EPOLL)
+#if defined(TARGET_NR_epoll_create)
+    case TARGET_NR_epoll_create:
+        ret = get_errno(epoll_create(arg1));
+        break;
+#endif
+#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
+    case TARGET_NR_epoll_create1:
+        ret = get_errno(epoll_create1(arg1));
+        break;
+#endif
+#if defined(TARGET_NR_epoll_ctl)
+    case TARGET_NR_epoll_ctl:
+    {
+        struct epoll_event ep;
+        struct epoll_event *epp = 0;
+        if (arg4) {
+            struct target_epoll_event *target_ep;
+            if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
+                goto efault;
+            }
+            ep.events = tswap32(target_ep->events);
+            /* The epoll_data_t union is just opaque data to the kernel,
+             * so we transfer all 64 bits across and need not worry what
+             * actual data type it is.
+             */
+            ep.data.u64 = tswap64(target_ep->data.u64);
+            unlock_user_struct(target_ep, arg4, 0);
+            epp = &ep;
+        }
+        ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
+        break;
+    }
+#endif
+
+#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
+#define IMPLEMENT_EPOLL_PWAIT
+#endif
+#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
+#if defined(TARGET_NR_epoll_wait)
+    case TARGET_NR_epoll_wait:
+#endif
+#if defined(IMPLEMENT_EPOLL_PWAIT)
+    case TARGET_NR_epoll_pwait:
+#endif
+    {
+        struct target_epoll_event *target_ep;
+        struct epoll_event *ep;
+        int epfd = arg1;
+        int maxevents = arg3;
+        int timeout = arg4;
+
+        target_ep = lock_user(VERIFY_WRITE, arg2,
+                              maxevents * sizeof(struct target_epoll_event), 1);
+        if (!target_ep) {
+            goto efault;
+        }
+
+        ep = alloca(maxevents * sizeof(struct epoll_event));
+
+        switch (num) {
+#if defined(IMPLEMENT_EPOLL_PWAIT)
+        case TARGET_NR_epoll_pwait:
+        {
+            target_sigset_t *target_set;
+            sigset_t _set, *set = &_set;
+
+            if (arg5) {
+                target_set = lock_user(VERIFY_READ, arg5,
+                                       sizeof(target_sigset_t), 1);
+                if (!target_set) {
+                    unlock_user(target_ep, arg2, 0);
+                    goto efault;
+                }
+                target_to_host_sigset(set, target_set);
+                unlock_user(target_set, arg5, 0);
+            } else {
+                set = NULL;
+            }
+
+            ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
+            break;
+        }
+#endif
+#if defined(TARGET_NR_epoll_wait)
+        case TARGET_NR_epoll_wait:
+            ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
+            break;
+#endif
+        default:
+            ret = -TARGET_ENOSYS;
+        }
+        if (!is_error(ret)) {
+            int i;
+            for (i = 0; i < ret; i++) {
+                target_ep[i].events = tswap32(ep[i].events);
+                target_ep[i].data.u64 = tswap64(ep[i].data.u64);
+            }
+        }
+        unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
+        break;
+    }
+#endif
+#endif
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 4742ac0..702652c 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2206,3 +2206,16 @@ struct target_mq_attr {
 #define FUTEX_CLOCK_REALTIME    256
 #define FUTEX_CMD_MASK          ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
 
+#ifdef CONFIG_EPOLL
+typedef union target_epoll_data {
+    abi_ulong ptr;
+    abi_ulong fd;
+    uint32_t u32;
+    uint64_t u64;
+} target_epoll_data_t;
+
+struct target_epoll_event {
+    uint32_t events;
+    target_epoll_data_t data;
+};
+#endif
commit d2ee72a5b17d95fe0e57e496f1b2ddb2464b5c08
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Tue Feb 15 21:10:44 2011 +0100

    linux-user: in linux-user/strace.c, tswap() is useless
    
    Syscall parameters are already swapped by the caller.
    
    This patch removes useless tswap() from strace.c
    
    $ QEMU_STRACE=1 chroot /m68k mknod myramdisk b 1 1
    with tswap()
    ...
    29944 mknod("myramdisk",026630200000) = 0
    ...
    
    without tswap()
    
    ...
    30042 mknod("myramdisk",S_IFBLK|0666,makedev(1,1)) = 0
    ...
    
    natively:
    
    $ strace touch mytouch
    ...
    open("mytouch", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
    ...
    
    $ QEMU_STRACE=1 chroot /m68k touch mytouch
    with tswap()
    ...
    30368 open("/usr/share/locale/locale.alias",O_RDONLY) = 3
    30368 fstat64(50331648,0x4080032c) = 0
    ...
    30368 open("mytouch",O_RDONLY|O_CREAT|O_LARGEFILE|O_NOCTTY|O_NONBLOCK|0x1) = 0
    ...
    without tswap()
    ...
    30572 open("/usr/share/locale/locale.alias",O_RDONLY) = 3
    30572 fstat64(3,0x4080032c) = 0
    ...
    30572 open("mytouch",O_WRONLY|O_CREAT|O_LARGEFILE|O_NOCTTY|O_NONBLOCK,0666) = 0
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    
    Fixes by Riku Voipio: add casts
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 05277c0..8dd398b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -441,14 +441,11 @@ get_comma(int last)
 }
 
 static void
-print_flags(const struct flags *f, abi_long tflags, int last)
+print_flags(const struct flags *f, abi_long flags, int last)
 {
     const char *sep = "";
-    int flags;
     int n;
 
-    flags = (int)tswap32(tflags);
-
     if ((flags == 0) && (f->f_value == 0)) {
         gemu_log("%s%s", f->f_string, get_comma(last));
         return;
@@ -465,36 +462,33 @@ print_flags(const struct flags *f, abi_long tflags, int last)
     if (n > 0) {
         /* print rest of the flags as numeric */
         if (flags != 0) {
-            gemu_log("%s%#x%s", sep, flags, get_comma(last));
+            gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last));
         } else {
             gemu_log("%s", get_comma(last));
         }
     } else {
         /* no string version of flags found, print them in hex then */
-        gemu_log("%#x%s", flags, get_comma(last));
+        gemu_log("%#x%s", (unsigned int)flags, get_comma(last));
     }
 }
 
 static void
-print_at_dirfd(abi_long tdirfd, int last)
+print_at_dirfd(abi_long dirfd, int last)
 {
-    int dirfd = tswap32(tdirfd);
-
 #ifdef AT_FDCWD
     if (dirfd == AT_FDCWD) {
         gemu_log("AT_FDCWD%s", get_comma(last));
         return;
     }
 #endif
-    gemu_log("%d%s", dirfd, get_comma(last));
+    gemu_log("%d%s", (int)dirfd, get_comma(last));
 }
 
 static void
-print_file_mode(abi_long tmode, int last)
+print_file_mode(abi_long mode, int last)
 {
     const char *sep = "";
     const struct flags *m;
-    mode_t mode = (mode_t)tswap32(tmode);
 
     for (m = &mode_flags[0]; m->f_string != NULL; m++) {
         if ((m->f_value & mode) == m->f_value) {
@@ -508,16 +502,14 @@ print_file_mode(abi_long tmode, int last)
     mode &= ~S_IFMT;
     /* print rest of the mode as octal */
     if (mode != 0)
-        gemu_log("%s%#o", sep, mode);
+        gemu_log("%s%#o", sep, (unsigned int)mode);
 
     gemu_log("%s", get_comma(last));
 }
 
 static void
-print_open_flags(abi_long tflags, int last)
+print_open_flags(abi_long flags, int last)
 {
-    int flags = tswap32(tflags);
-
     print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1);
     flags &= ~TARGET_O_ACCMODE;
     if (flags == 0) {
@@ -620,7 +612,7 @@ print_accept(const struct syscallname *name,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
     print_syscall_prologue(name);
-    print_raw_param("%d", tswap32(arg0), 0);
+    print_raw_param("%d", arg0, 0);
     print_pointer(arg1, 0);
     print_number(arg2, 1);
     print_syscall_epilogue(name);
@@ -698,7 +690,7 @@ print_execv(const struct syscallname *name,
 {
     print_syscall_prologue(name);
     print_string(arg0, 0);
-    print_raw_param("0x" TARGET_ABI_FMT_lx, tswapl(arg1), 1);
+    print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1);
     print_syscall_epilogue(name);
 }
 #endif
@@ -742,13 +734,8 @@ print_fchownat(const struct syscallname *name,
     print_syscall_prologue(name);
     print_at_dirfd(arg0, 0);
     print_string(arg1, 0);
-#ifdef USE_UID16
-    print_raw_param("%d", tswap16(arg2), 0);
-    print_raw_param("%d", tswap16(arg3), 0);
-#else
-    print_raw_param("%d", tswap32(arg2), 0);
-    print_raw_param("%d", tswap32(arg3), 0);
-#endif
+    print_raw_param("%d", arg2, 0);
+    print_raw_param("%d", arg3, 0);
     print_flags(at_file_flags, arg4, 1);
     print_syscall_epilogue(name);
 }
@@ -761,7 +748,7 @@ print_fcntl(const struct syscallname *name,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
     print_syscall_prologue(name);
-    print_raw_param("%d", tswap32(arg0), 0);
+    print_raw_param("%d", arg0, 0);
     print_flags(fcntl_flags, arg1, 0);
     /*
      * TODO: check flags and print following argument only
@@ -842,7 +829,7 @@ print_fstat(const struct syscallname *name,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
     print_syscall_prologue(name);
-    print_raw_param("%d", tswap32(arg0), 0);
+    print_raw_param("%d", arg0, 0);
     print_pointer(arg1, 1);
     print_syscall_epilogue(name);
 }
@@ -894,14 +881,14 @@ print_mknod(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
-    int hasdev = (tswapl(arg1) & (S_IFCHR|S_IFBLK));
+    int hasdev = (arg1 & (S_IFCHR|S_IFBLK));
 
     print_syscall_prologue(name);
     print_string(arg0, 0);
     print_file_mode(arg1, (hasdev == 0));
     if (hasdev) {
-        print_raw_param("makedev(%d", major(tswapl(arg2)), 0);
-        print_raw_param("%d)", minor(tswapl(arg2)), 1);
+        print_raw_param("makedev(%d", major(arg2), 0);
+        print_raw_param("%d)", minor(arg2), 1);
     }
     print_syscall_epilogue(name);
 }
@@ -913,15 +900,15 @@ print_mknodat(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
-    int hasdev = (tswapl(arg2) & (S_IFCHR|S_IFBLK));
+    int hasdev = (arg2 & (S_IFCHR|S_IFBLK));
 
     print_syscall_prologue(name);
     print_at_dirfd(arg0, 0);
     print_string(arg1, 0);
     print_file_mode(arg2, (hasdev == 0));
     if (hasdev) {
-        print_raw_param("makedev(%d", major(tswapl(arg3)), 0);
-        print_raw_param("%d)", minor(tswapl(arg3)), 1);
+        print_raw_param("makedev(%d", major(arg3), 0);
+        print_raw_param("%d)", minor(arg3), 1);
     }
     print_syscall_epilogue(name);
 }
@@ -933,7 +920,7 @@ print_mq_open(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
-    int is_creat = (tswapl(arg1) & TARGET_O_CREAT);
+    int is_creat = (arg1 & TARGET_O_CREAT);
 
     print_syscall_prologue(name);
     print_string(arg0, 0);
@@ -952,7 +939,7 @@ print_open(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
-    int is_creat = (tswap32(arg1) & TARGET_O_CREAT);
+    int is_creat = (arg1 & TARGET_O_CREAT);
 
     print_syscall_prologue(name);
     print_string(arg0, 0);
@@ -969,7 +956,7 @@ print_openat(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
-    int is_creat = (tswap32(arg2) & TARGET_O_CREAT);
+    int is_creat = (arg2 & TARGET_O_CREAT);
 
     print_syscall_prologue(name);
     print_at_dirfd(arg0, 0);
@@ -1018,7 +1005,7 @@ print_readlink(const struct syscallname *name,
     print_syscall_prologue(name);
     print_string(arg0, 0);
     print_pointer(arg1, 0);
-    print_raw_param("%u", tswapl(arg2), 1);
+    print_raw_param("%u", arg2, 1);
     print_syscall_epilogue(name);
 }
 #endif
@@ -1033,7 +1020,7 @@ print_readlinkat(const struct syscallname *name,
     print_at_dirfd(arg0, 0);
     print_string(arg1, 0);
     print_pointer(arg2, 0);
-    print_raw_param("%u", tswapl(arg3), 1);
+    print_raw_param("%u", arg3, 1);
     print_syscall_epilogue(name);
 }
 #endif
@@ -1223,11 +1210,11 @@ print_mmap(const struct syscallname *name,
 {
     print_syscall_prologue(name);
     print_pointer(arg0, 0);
-    print_raw_param("%d", tswapl(arg1), 0);
+    print_raw_param("%d", arg1, 0);
     print_flags(mmap_prot_flags, arg2, 0);
     print_flags(mmap_flags, arg3, 0);
-    print_raw_param("%d", tswapl(arg4), 0);
-    print_raw_param("%#x", tswapl(arg5), 1);
+    print_raw_param("%d", arg4, 0);
+    print_raw_param("%#x", arg5, 1);
     print_syscall_epilogue(name);
 }
 #define print_mmap2     print_mmap
@@ -1241,7 +1228,7 @@ print_mprotect(const struct syscallname *name,
 {
     print_syscall_prologue(name);
     print_pointer(arg0, 0);
-    print_raw_param("%d", tswapl(arg1), 0);
+    print_raw_param("%d", arg1, 0);
     print_flags(mmap_prot_flags, arg2, 1);
     print_syscall_epilogue(name);
 }
@@ -1255,7 +1242,7 @@ print_munmap(const struct syscallname *name,
 {
     print_syscall_prologue(name);
     print_pointer(arg0, 0);
-    print_raw_param("%d", tswapl(arg1), 1);
+    print_raw_param("%d", arg1, 1);
     print_syscall_epilogue(name);
 }
 #endif
@@ -1269,7 +1256,7 @@ if( cmd == val ) { \
     return; \
 }
 
-    int cmd = (int)tswap32(tflag);
+    int cmd = (int)tflag;
 #ifdef FUTEX_PRIVATE_FLAG
     if (cmd & FUTEX_PRIVATE_FLAG) {
         gemu_log("FUTEX_PRIVATE_FLAG|");
@@ -1303,10 +1290,10 @@ print_futex(const struct syscallname *name,
     print_syscall_prologue(name);
     print_pointer(arg0, 0);
     print_futex_op(arg1, 0);
-    print_raw_param(",%d", tswapl(arg2), 0);
+    print_raw_param(",%d", arg2, 0);
     print_pointer(arg3, 0); /* struct timespec */
     print_pointer(arg4, 0);
-    print_raw_param("%d", tswapl(arg4), 1);
+    print_raw_param("%d", arg4, 1);
     print_syscall_epilogue(name);
 }
 #endif
commit 4de596cb5092fbe125beb5e0b684cf0da7359624
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Tue Feb 15 21:10:43 2011 +0100

    linux-user: add rmdir() strace
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 1836666..05277c0 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -876,6 +876,18 @@ print_mkdirat(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_rmdir
+static void
+print_rmdir(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_string(arg0, 0);
+    print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_mknod
 static void
 print_mknod(const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d7be0e7..563a67f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -495,6 +495,9 @@
 #ifdef TARGET_NR_mkdirat
 { TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL },
 #endif
+#ifdef TARGET_NR_rmdir
+{ TARGET_NR_rmdir, "rmdir" , NULL, print_rmdir, NULL },
+#endif
 #ifdef TARGET_NR_mknod
 { TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL },
 #endif
commit 79f2b6fcdb7c06cdce6eccc796f5651f3efb843e
Merge: c5d69e6... 16fde5f...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 16 08:47:13 2011 -0600

    Merge remote branch 'kwolf/for-anthony' into staging

commit c5d69e6bbf37bf5e3882060764b15e018e6a5321
Merge: 630ecca... 0ec329d...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 16 08:47:07 2011 -0600

    Merge remote branch 'qemu-kvm/uq/master' into staging

diff --cc cpus.c
index 2d92090,468544c..0f33945
--- a/cpus.c
+++ b/cpus.c
@@@ -409,13 -687,12 +687,14 @@@ int qemu_init_main_loop(void
  
      /* Note eventfd must be drained before signalfd handlers run */
      ret = qemu_event_init();
-     if (ret)
+     if (ret) {
          return ret;
+     }
  
 -    qemu_cond_init(&qemu_pause_cond);
 +    qemu_cond_init(&qemu_cpu_cond);
      qemu_cond_init(&qemu_system_cond);
 +    qemu_cond_init(&qemu_pause_cond);
 +    qemu_cond_init(&qemu_work_cond);
      qemu_mutex_init(&qemu_fair_mutex);
      qemu_mutex_init(&qemu_global_mutex);
      qemu_mutex_lock(&qemu_global_mutex);
commit 630ecca0da959e65acad1ee0bf3a631bbb7ee052
Author: Tristan Gingold <gingold at adacore.com>
Date:   Tue Feb 15 09:39:54 2011 +0100

    Handle icount for powerpc tbl/tbu/decr load and store.
    
    Handle option '-icount X' on powerpc targets.
    
    Signed-off-by: Tristan Gingold <gingold at adacore.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index dfcd949..7c08b1c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -154,12 +154,26 @@ static void spr_read_ureg (void *opaque, int gprn, int sprn)
 #if !defined(CONFIG_USER_ONLY)
 static void spr_read_decr (void *opaque, int gprn, int sprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_load_decr(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 
 static void spr_write_decr (void *opaque, int sprn, int gprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_store_decr(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 #endif
 
@@ -167,12 +181,26 @@ static void spr_write_decr (void *opaque, int sprn, int gprn)
 /* Time base */
 static void spr_read_tbl (void *opaque, int gprn, int sprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_load_tbl(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 
 static void spr_read_tbu (void *opaque, int gprn, int sprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_load_tbu(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 
 __attribute__ (( unused ))
@@ -190,12 +218,26 @@ static void spr_read_atbu (void *opaque, int gprn, int sprn)
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_tbl (void *opaque, int sprn, int gprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_store_tbl(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 
 static void spr_write_tbu (void *opaque, int sprn, int gprn)
 {
+    if (use_icount) {
+        gen_io_start();
+    }
     gen_helper_store_tbu(cpu_gpr[gprn]);
+    if (use_icount) {
+        gen_io_end();
+        gen_stop_exception(opaque);
+    }
 }
 
 __attribute__ (( unused ))
commit 0ec329dab938e2d97d12a91f8ed15fec27b325e0
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:26 2011 +0100

    kvm: x86: Introduce kvmclock device to save/restore its state
    
    If kvmclock is used, which implies the kernel supports it, register a
    kvmclock device with the sysbus. Its main purpose is to save and restore
    the kernel state on migration, but this will also allow to visualize it
    one day.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Glauber Costa <glommer at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index a6c30dd..5a0fd40 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -37,7 +37,7 @@ ifndef CONFIG_HAIKU
 LIBS+=-lm
 endif
 
-kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
+kvm.o kvm-all.o vhost.o vhost_net.o kvmclock.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
 
 config-target.h: config-target.h-timestamp
 config-target.h-timestamp: config-target.mak
@@ -218,7 +218,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o applesmc.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pc_piix.o
+obj-i386-y += pc_piix.o kvmclock.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
diff --git a/hw/kvmclock.c b/hw/kvmclock.c
new file mode 100644
index 0000000..b6ceddf
--- /dev/null
+++ b/hw/kvmclock.c
@@ -0,0 +1,125 @@
+/*
+ * QEMU KVM support, paravirtual clock device
+ *
+ * Copyright (C) 2011 Siemens AG
+ *
+ * Authors:
+ *  Jan Kiszka        <jan.kiszka at siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "sysbus.h"
+#include "kvm.h"
+#include "kvmclock.h"
+
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
+
+#include <linux/kvm.h>
+#include <linux/kvm_para.h>
+
+typedef struct KVMClockState {
+    SysBusDevice busdev;
+    uint64_t clock;
+    bool clock_valid;
+} KVMClockState;
+
+static void kvmclock_pre_save(void *opaque)
+{
+    KVMClockState *s = opaque;
+    struct kvm_clock_data data;
+    int ret;
+
+    if (s->clock_valid) {
+        return;
+    }
+    ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
+        data.clock = 0;
+    }
+    s->clock = data.clock;
+    /*
+     * If the VM is stopped, declare the clock state valid to avoid re-reading
+     * it on next vmsave (which would return a different value). Will be reset
+     * when the VM is continued.
+     */
+    s->clock_valid = !vm_running;
+}
+
+static int kvmclock_post_load(void *opaque, int version_id)
+{
+    KVMClockState *s = opaque;
+    struct kvm_clock_data data;
+
+    data.clock = s->clock;
+    data.flags = 0;
+    return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
+}
+
+static void kvmclock_vm_state_change(void *opaque, int running, int reason)
+{
+    KVMClockState *s = opaque;
+
+    if (running) {
+        s->clock_valid = false;
+    }
+}
+
+static int kvmclock_init(SysBusDevice *dev)
+{
+    KVMClockState *s = FROM_SYSBUS(KVMClockState, dev);
+
+    qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
+    return 0;
+}
+
+static const VMStateDescription kvmclock_vmsd = {
+    .name = "kvmclock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = kvmclock_pre_save,
+    .post_load = kvmclock_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(clock, KVMClockState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo kvmclock_info = {
+    .qdev.name = "kvmclock",
+    .qdev.size = sizeof(KVMClockState),
+    .qdev.vmsd = &kvmclock_vmsd,
+    .qdev.no_user = 1,
+    .init = kvmclock_init,
+};
+
+/* Note: Must be called after VCPU initialization. */
+void kvmclock_create(void)
+{
+    if (kvm_enabled() &&
+        first_cpu->cpuid_kvm_features & (1ULL << KVM_FEATURE_CLOCKSOURCE)) {
+        sysbus_create_simple("kvmclock", -1, NULL);
+    }
+}
+
+static void kvmclock_register_device(void)
+{
+    if (kvm_enabled()) {
+        sysbus_register_withprop(&kvmclock_info);
+    }
+}
+
+device_init(kvmclock_register_device);
+
+#else /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */
+
+void kvmclock_create(void)
+{
+}
+#endif /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */
diff --git a/hw/kvmclock.h b/hw/kvmclock.h
new file mode 100644
index 0000000..7a83cbe
--- /dev/null
+++ b/hw/kvmclock.h
@@ -0,0 +1,14 @@
+/*
+ * QEMU KVM support, paravirtual clock device
+ *
+ * Copyright (C) 2011 Siemens AG
+ *
+ * Authors:
+ *  Jan Kiszka        <jan.kiszka at siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+void kvmclock_create(void);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index d0bd0cd..2918454 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -32,6 +32,7 @@
 #include "boards.h"
 #include "ide.h"
 #include "kvm.h"
+#include "kvmclock.h"
 #include "sysemu.h"
 #include "sysbus.h"
 #include "arch_init.h"
@@ -66,7 +67,8 @@ static void pc_init1(ram_addr_t ram_size,
                      const char *kernel_cmdline,
                      const char *initrd_filename,
                      const char *cpu_model,
-                     int pci_enabled)
+                     int pci_enabled,
+                     int kvmclock_enabled)
 {
     int i;
     ram_addr_t below_4g_mem_size, above_4g_mem_size;
@@ -86,6 +88,10 @@ static void pc_init1(ram_addr_t ram_size,
 
     pc_cpus_init(cpu_model);
 
+    if (kvmclock_enabled) {
+        kvmclock_create();
+    }
+
     /* allocate ram and load rom/bios */
     pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
                    &below_4g_mem_size, &above_4g_mem_size);
@@ -193,7 +199,19 @@ static void pc_init_pci(ram_addr_t ram_size,
 {
     pc_init1(ram_size, boot_device,
              kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1);
+             initrd_filename, cpu_model, 1, 1);
+}
+
+static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
+                                    const char *boot_device,
+                                    const char *kernel_filename,
+                                    const char *kernel_cmdline,
+                                    const char *initrd_filename,
+                                    const char *cpu_model)
+{
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1, 0);
 }
 
 static void pc_init_isa(ram_addr_t ram_size,
@@ -207,7 +225,7 @@ static void pc_init_isa(ram_addr_t ram_size,
         cpu_model = "486";
     pc_init1(ram_size, boot_device,
              kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0);
+             initrd_filename, cpu_model, 0, 1);
 }
 
 static QEMUMachine pc_machine = {
@@ -222,7 +240,7 @@ static QEMUMachine pc_machine = {
 static QEMUMachine pc_machine_v0_13 = {
     .name = "pc-0.13",
     .desc = "Standard PC",
-    .init = pc_init_pci,
+    .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         {
@@ -249,7 +267,7 @@ static QEMUMachine pc_machine_v0_13 = {
 static QEMUMachine pc_machine_v0_12 = {
     .name = "pc-0.12",
     .desc = "Standard PC",
-    .init = pc_init_pci,
+    .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         {
@@ -280,7 +298,7 @@ static QEMUMachine pc_machine_v0_12 = {
 static QEMUMachine pc_machine_v0_11 = {
     .name = "pc-0.11",
     .desc = "Standard PC, qemu 0.11",
-    .init = pc_init_pci,
+    .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         {
@@ -319,7 +337,7 @@ static QEMUMachine pc_machine_v0_11 = {
 static QEMUMachine pc_machine_v0_10 = {
     .name = "pc-0.10",
     .desc = "Standard PC, qemu 0.10",
-    .init = pc_init_pci,
+    .init = pc_init_pci_no_kvmclock,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         {
commit 6a7af8cb04c345eb1ed9d95250ef3ad4400e65c5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:25 2011 +0100

    kvm: Make kvm_state globally available
    
    KVM-assisted devices need access to it but we have no clean channel to
    distribute a reference. As a workaround until there is a better
    solution, export kvm_state for global use, though use should remain
    restricted to the mentioned scenario.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index ecac0b3..e6a7de4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -78,7 +78,7 @@ struct KVMState
     int many_ioeventfds;
 };
 
-static KVMState *kvm_state;
+KVMState *kvm_state;
 
 static const KVMCapabilityInfo kvm_required_capabilites[] = {
     KVM_CAP_INFO(USER_MEMORY),
diff --git a/kvm.h b/kvm.h
index 4caa6ec..59b2c29 100644
--- a/kvm.h
+++ b/kvm.h
@@ -85,6 +85,7 @@ int kvm_on_sigbus(int code, void *addr);
 
 struct KVMState;
 typedef struct KVMState KVMState;
+extern KVMState *kvm_state;
 
 int kvm_ioctl(KVMState *s, int type, ...);
 
commit 638a84af9fced4b410243e45f755552303a17a3c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:24 2011 +0100

    cirrus: Remove obsolete kvm.h include
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 5f45b5d..2724f7b 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -31,7 +31,6 @@
 #include "pci.h"
 #include "console.h"
 #include "vga_int.h"
-#include "kvm.h"
 #include "loader.h"
 
 /*
commit e5896b12e20b86ba9d16582888d60cf5cb286517
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Mon Feb 7 12:19:23 2011 +0100

    Introduce log_start/log_stop in CPUPhysMemoryClient
    
    In order to use log_start/log_stop with Xen as well in the vga code,
    this two operations have been put in CPUPhysMemoryClient.
    
    The two new functions cpu_physical_log_start,cpu_physical_log_stop are
    used in hw/vga.c and replace the kvm_log_start/stop. With this, vga does
    no longer depends on kvm header.
    
    [ Jan: rebasing and style fixlets ]
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index ffbd6a4..87b0f86 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -959,6 +959,12 @@ int cpu_physical_memory_get_dirty_tracking(void);
 int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
                                    target_phys_addr_t end_addr);
 
+int cpu_physical_log_start(target_phys_addr_t start_addr,
+                           ram_addr_t size);
+
+int cpu_physical_log_stop(target_phys_addr_t start_addr,
+                          ram_addr_t size);
+
 void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/cpu-common.h b/cpu-common.h
index 6d4a898..54d21d4 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -96,6 +96,10 @@ struct CPUPhysMemoryClient {
                              target_phys_addr_t end_addr);
     int (*migration_log)(struct CPUPhysMemoryClient *client,
                          int enable);
+    int (*log_start)(struct CPUPhysMemoryClient *client,
+                     target_phys_addr_t phys_addr, ram_addr_t size);
+    int (*log_stop)(struct CPUPhysMemoryClient *client,
+                    target_phys_addr_t phys_addr, ram_addr_t size);
     QLIST_ENTRY(CPUPhysMemoryClient) list;
 };
 
diff --git a/exec.c b/exec.c
index 1b70dc1..d611100 100644
--- a/exec.c
+++ b/exec.c
@@ -2078,6 +2078,36 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
     return ret;
 }
 
+int cpu_physical_log_start(target_phys_addr_t start_addr,
+                           ram_addr_t size)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        if (client->log_start) {
+            int r = client->log_start(client, start_addr, size);
+            if (r < 0) {
+                return r;
+            }
+        }
+    }
+    return 0;
+}
+
+int cpu_physical_log_stop(target_phys_addr_t start_addr,
+                          ram_addr_t size)
+{
+    CPUPhysMemoryClient *client;
+    QLIST_FOREACH(client, &memory_client_list, list) {
+        if (client->log_stop) {
+            int r = client->log_stop(client, start_addr, size);
+            if (r < 0) {
+                return r;
+            }
+        }
+    }
+    return 0;
+}
+
 static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 {
     ram_addr_t ram_addr;
diff --git a/hw/vga.c b/hw/vga.c
index e2151a2..c22b8af 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -28,7 +28,6 @@
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
-#include "kvm.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
@@ -1573,34 +1572,36 @@ static void vga_sync_dirty_bitmap(VGACommonState *s)
 
 void vga_dirty_log_start(VGACommonState *s)
 {
-    if (kvm_enabled() && s->map_addr)
-        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
+    if (s->map_addr) {
+        cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
+    }
 
-    if (kvm_enabled() && s->lfb_vram_mapped) {
-        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
-        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
+    if (s->lfb_vram_mapped) {
+        cpu_physical_log_start(isa_mem_base + 0xa0000, 0x8000);
+        cpu_physical_log_start(isa_mem_base + 0xa8000, 0x8000);
     }
 
 #ifdef CONFIG_BOCHS_VBE
-    if (kvm_enabled() && s->vbe_mapped) {
-        kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
+    if (s->vbe_mapped) {
+        cpu_physical_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
     }
 #endif
 }
 
 void vga_dirty_log_stop(VGACommonState *s)
 {
-    if (kvm_enabled() && s->map_addr)
-	kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
+    if (s->map_addr) {
+        cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
+    }
 
-    if (kvm_enabled() && s->lfb_vram_mapped) {
-	kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
-	kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
+    if (s->lfb_vram_mapped) {
+        cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
+        cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
     }
 
 #ifdef CONFIG_BOCHS_VBE
-    if (kvm_enabled() && s->vbe_mapped) {
-	kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
+    if (s->vbe_mapped) {
+        cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
     }
 #endif
 }
diff --git a/hw/vhost.c b/hw/vhost.c
index 38cc3b3..0ca3507 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -607,6 +607,8 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     hdev->client.set_memory = vhost_client_set_memory;
     hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
     hdev->client.migration_log = vhost_client_migration_log;
+    hdev->client.log_start = NULL;
+    hdev->client.log_stop = NULL;
     hdev->mem = qemu_mallocz(offsetof(struct vhost_memory, regions));
     hdev->log = NULL;
     hdev->log_size = 0;
diff --git a/kvm-all.c b/kvm-all.c
index 14b6c1e..ecac0b3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -274,13 +274,15 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
     return kvm_set_user_memory_region(s, mem);
 }
 
-int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
+static int kvm_log_start(CPUPhysMemoryClient *client,
+                         target_phys_addr_t phys_addr, ram_addr_t size)
 {
     return kvm_dirty_pages_log_change(phys_addr, size, KVM_MEM_LOG_DIRTY_PAGES,
                                       KVM_MEM_LOG_DIRTY_PAGES);
 }
 
-int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
+static int kvm_log_stop(CPUPhysMemoryClient *client,
+                        target_phys_addr_t phys_addr, ram_addr_t size)
 {
     return kvm_dirty_pages_log_change(phys_addr, size, 0,
                                       KVM_MEM_LOG_DIRTY_PAGES);
@@ -644,6 +646,8 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
     .set_memory = kvm_client_set_memory,
     .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
     .migration_log = kvm_client_migration_log,
+    .log_start = kvm_log_start,
+    .log_stop = kvm_log_stop,
 };
 
 int kvm_init(void)
diff --git a/kvm-stub.c b/kvm-stub.c
index d6b6c8e..30f6ec3 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -33,16 +33,6 @@ int kvm_init_vcpu(CPUState *env)
     return -ENOSYS;
 }
 
-int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
-{
-    return -ENOSYS;
-}
-
-int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
-{
-    return -ENOSYS;
-}
-
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 {
     return -ENOSYS;
diff --git a/kvm.h b/kvm.h
index 7a4d550..4caa6ec 100644
--- a/kvm.h
+++ b/kvm.h
@@ -58,9 +58,6 @@ int kvm_init_vcpu(CPUState *env);
 int kvm_cpu_exec(CPUState *env);
 
 #if !defined(CONFIG_USER_ONLY)
-int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);
-int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
-
 void kvm_setup_guest_memory(void *start, size_t size);
 
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
commit 8e045ac407029c004e31eb46b0586309d618fbbd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:22 2011 +0100

    kvm: Remove unneeded memory slot reservation
    
    The number of slots and the location of private ones changed several
    times in KVM's early days. However, it's stable since 2.6.29 (our
    required baseline), and slots 8..11 are no longer reserved since then.
    So remove this unneeded restriction.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 802c6b8..14b6c1e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -91,10 +91,6 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
     int i;
 
     for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
-        /* KVM private memory slots */
-        if (i >= 8 && i < 12) {
-            continue;
-        }
         if (s->slots[i].memory_size == 0) {
             return &s->slots[i];
         }
commit ce377af399563195d066d5fee0c7b717967932ee
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:21 2011 +0100

    kvm: x86: Catch and report failing IRQ and NMI injections
    
    We do not need to abort, but the user should be notified that weird
    things go on.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 8668cb3..0aa0a41 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1442,11 +1442,17 @@ int kvm_arch_get_registers(CPUState *env)
 
 void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
+    int ret;
+
     /* Inject NMI */
     if (env->interrupt_request & CPU_INTERRUPT_NMI) {
         env->interrupt_request &= ~CPU_INTERRUPT_NMI;
         DPRINTF("injected NMI\n");
-        kvm_vcpu_ioctl(env, KVM_NMI);
+        ret = kvm_vcpu_ioctl(env, KVM_NMI);
+        if (ret < 0) {
+            fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
+                    strerror(-ret));
+        }
     }
 
     if (!kvm_irqchip_in_kernel()) {
@@ -1467,9 +1473,13 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
                 struct kvm_interrupt intr;
 
                 intr.irq = irq;
-                /* FIXME: errors */
                 DPRINTF("injected interrupt %d\n", irq);
-                kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
+                ret = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
+                if (ret < 0) {
+                    fprintf(stderr,
+                            "KVM: injection failed, interrupt lost (%s)\n",
+                            strerror(-ret));
+                }
             }
         }
 
commit 7a39fe588251ba042c91bf23d53b0ba820bf964c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:20 2011 +0100

    kvm: Drop return values from kvm_arch_pre/post_run
    
    We do not check them, and the only arch with non-empty implementations
    always returns 0 (this is also true for qemu-kvm).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Alexander Graf <agraf at suse.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm.h b/kvm.h
index b2fb5c6..7a4d550 100644
--- a/kvm.h
+++ b/kvm.h
@@ -99,12 +99,11 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 
 extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
 
-int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
+void kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
+void kvm_arch_post_run(CPUState *env, struct kvm_run *run);
 
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
 
-int kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
-
 int kvm_arch_process_irqchip_events(CPUState *env);
 
 int kvm_arch_get_registers(CPUState *env);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f02f478..8668cb3 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1440,7 +1440,7 @@ int kvm_arch_get_registers(CPUState *env)
     return 0;
 }
 
-int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
     /* Inject NMI */
     if (env->interrupt_request & CPU_INTERRUPT_NMI) {
@@ -1486,11 +1486,9 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
         DPRINTF("setting tpr\n");
         run->cr8 = cpu_get_apic_tpr(env->apic_state);
     }
-
-    return 0;
 }
 
-int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
     if (run->if_flag) {
         env->eflags |= IF_MASK;
@@ -1499,8 +1497,6 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     }
     cpu_set_apic_tpr(env->apic_state, run->cr8);
     cpu_set_apic_base(env->apic_state, run->apic_base);
-
-    return 0;
 }
 
 int kvm_arch_process_irqchip_events(CPUState *env)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 93ecc57..bd4012a 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -256,14 +256,12 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
-int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
-    return 0;
 }
 
-int kvm_arch_process_irqchip_events(CPUState *env)
+void kvm_arch_process_irqchip_events(CPUState *env)
 {
-    return 0;
 }
 
 static int kvmppc_handle_halt(CPUState *env)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 1702c46..b349812 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -169,14 +169,12 @@ int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
     return 0;
 }
 
-int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
-    return 0;
 }
 
-int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
+void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
-    return 0;
 }
 
 int kvm_arch_process_irqchip_events(CPUState *env)
commit db1669bcca7cc67d7301394d7d59dffb4c0fc9b0
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:19 2011 +0100

    kvm: x86: Prepare VCPU loop for in-kernel irqchip
    
    Effectively no functional change yet as kvm_irqchip_in_kernel still only
    returns 0, but this patch will allow qemu-kvm to adopt the VCPU loop of
    upsteam KVM.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 377a0a3..f02f478 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1442,11 +1442,6 @@ int kvm_arch_get_registers(CPUState *env)
 
 int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
-    /* Force the VCPU out of its inner loop to process the INIT request */
-    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
-        env->exit_request = 1;
-    }
-
     /* Inject NMI */
     if (env->interrupt_request & CPU_INTERRUPT_NMI) {
         env->interrupt_request &= ~CPU_INTERRUPT_NMI;
@@ -1454,35 +1449,43 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
         kvm_vcpu_ioctl(env, KVM_NMI);
     }
 
-    /* Try to inject an interrupt if the guest can accept it */
-    if (run->ready_for_interrupt_injection &&
-        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
-        (env->eflags & IF_MASK)) {
-        int irq;
-
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        irq = cpu_get_pic_interrupt(env);
-        if (irq >= 0) {
-            struct kvm_interrupt intr;
-            intr.irq = irq;
-            /* FIXME: errors */
-            DPRINTF("injected interrupt %d\n", irq);
-            kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
+    if (!kvm_irqchip_in_kernel()) {
+        /* Force the VCPU out of its inner loop to process the INIT request */
+        if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+            env->exit_request = 1;
         }
-    }
 
-    /* If we have an interrupt but the guest is not ready to receive an
-     * interrupt, request an interrupt window exit.  This will
-     * cause a return to userspace as soon as the guest is ready to
-     * receive interrupts. */
-    if ((env->interrupt_request & CPU_INTERRUPT_HARD)) {
-        run->request_interrupt_window = 1;
-    } else {
-        run->request_interrupt_window = 0;
-    }
+        /* Try to inject an interrupt if the guest can accept it */
+        if (run->ready_for_interrupt_injection &&
+            (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (env->eflags & IF_MASK)) {
+            int irq;
+
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            irq = cpu_get_pic_interrupt(env);
+            if (irq >= 0) {
+                struct kvm_interrupt intr;
+
+                intr.irq = irq;
+                /* FIXME: errors */
+                DPRINTF("injected interrupt %d\n", irq);
+                kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
+            }
+        }
 
-    DPRINTF("setting tpr\n");
-    run->cr8 = cpu_get_apic_tpr(env->apic_state);
+        /* If we have an interrupt but the guest is not ready to receive an
+         * interrupt, request an interrupt window exit.  This will
+         * cause a return to userspace as soon as the guest is ready to
+         * receive interrupts. */
+        if ((env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            run->request_interrupt_window = 1;
+        } else {
+            run->request_interrupt_window = 0;
+        }
+
+        DPRINTF("setting tpr\n");
+        run->cr8 = cpu_get_apic_tpr(env->apic_state);
+    }
 
     return 0;
 }
@@ -1502,6 +1505,10 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 
 int kvm_arch_process_irqchip_events(CPUState *env)
 {
+    if (kvm_irqchip_in_kernel()) {
+        return 0;
+    }
+
     if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
         env->halted = 0;
     }
commit 6792a57bf19ab37f61f5acf0f8e3003cf08814af
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:18 2011 +0100

    kvm: Separate TCG from KVM cpu execution
    
    Mixing up TCG bits with KVM already led to problems around eflags
    emulation on x86. Moreover, quite some code that TCG requires on cpu
    enty/exit is useless for KVM. So dispatch between tcg_cpu_exec and
    kvm_cpu_exec as early as possible.
    
    The core logic of cpu_halted from cpu_exec is added to
    kvm_arch_process_irqchip_events. Moving away from cpu_exec makes
    exception_index meaningless for KVM, we can simply pass the exit reason
    directly (only "EXCP_DEBUG vs. rest" is relevant).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 9c0b10d..b03b3a7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -226,13 +226,11 @@ int cpu_exec(CPUState *env1)
     }
 
 #if defined(TARGET_I386)
-    if (!kvm_enabled()) {
-        /* put eflags in CPU temporary format */
-        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-        DF = 1 - (2 * ((env->eflags >> 10) & 1));
-        CC_OP = CC_OP_EFLAGS;
-        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    }
+    /* put eflags in CPU temporary format */
+    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    DF = 1 - (2 * ((env->eflags >> 10) & 1));
+    CC_OP = CC_OP_EFLAGS;
+    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_M68K)
     env->cc_op = CC_OP_FLAGS;
@@ -257,7 +255,7 @@ int cpu_exec(CPUState *env1)
         if (setjmp(env->jmp_env) == 0) {
 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
 #undef env
-                    env = cpu_single_env;
+            env = cpu_single_env;
 #define env cpu_single_env
 #endif
             /* if an exception is pending, we execute it here */
@@ -316,11 +314,6 @@ int cpu_exec(CPUState *env1)
                 }
             }
 
-            if (kvm_enabled()) {
-                kvm_cpu_exec(env);
-                longjmp(env->jmp_env, 1);
-            }
-
             next_tb = 0; /* force lookup of first TB */
             for(;;) {
                 interrupt_request = env->interrupt_request;
diff --git a/cpus.c b/cpus.c
index c7e86c2..468544c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -800,8 +800,6 @@ static void qemu_kvm_wait_io_event(CPUState *env)
     qemu_wait_io_event_common(env);
 }
 
-static int qemu_cpu_exec(CPUState *env);
-
 static void *qemu_kvm_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
@@ -829,7 +827,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
 
     while (1) {
         if (cpu_can_run(env)) {
-            r = qemu_cpu_exec(env);
+            r = kvm_cpu_exec(env);
             if (r == EXCP_DEBUG) {
                 cpu_handle_debug_exception(env);
             }
@@ -1040,7 +1038,7 @@ void vm_stop(int reason)
 
 #endif
 
-static int qemu_cpu_exec(CPUState *env)
+static int tcg_cpu_exec(CPUState *env)
 {
     int ret;
 #ifdef CONFIG_PROFILER
@@ -1095,9 +1093,11 @@ bool cpu_exec_all(void)
             break;
         }
         if (cpu_can_run(env)) {
-            r = qemu_cpu_exec(env);
             if (kvm_enabled()) {
+                r = kvm_cpu_exec(env);
                 qemu_kvm_eat_signals(env);
+            } else {
+                r = tcg_cpu_exec(env);
             }
             if (r == EXCP_DEBUG) {
                 cpu_handle_debug_exception(env);
diff --git a/kvm-all.c b/kvm-all.c
index 19cf188..802c6b8 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -895,10 +895,11 @@ int kvm_cpu_exec(CPUState *env)
 
     if (kvm_arch_process_irqchip_events(env)) {
         env->exit_request = 0;
-        env->exception_index = EXCP_HLT;
-        return 0;
+        return EXCP_HLT;
     }
 
+    cpu_single_env = env;
+
     do {
         if (env->kvm_vcpu_dirty) {
             kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
@@ -927,7 +928,6 @@ int kvm_cpu_exec(CPUState *env)
         kvm_flush_coalesced_mmio_buffer();
 
         if (ret == -EINTR || ret == -EAGAIN) {
-            cpu_exit(env);
             DPRINTF("io window exit\n");
             ret = 0;
             break;
@@ -978,8 +978,8 @@ int kvm_cpu_exec(CPUState *env)
             DPRINTF("kvm_exit_debug\n");
 #ifdef KVM_CAP_SET_GUEST_DEBUG
             if (kvm_arch_debug(&run->debug.arch)) {
-                env->exception_index = EXCP_DEBUG;
-                return 0;
+                ret = EXCP_DEBUG;
+                goto out;
             }
             /* re-enter, this exception was guest-internal */
             ret = 1;
@@ -995,13 +995,12 @@ int kvm_cpu_exec(CPUState *env)
     if (ret < 0) {
         cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
         vm_stop(VMSTOP_PANIC);
-        env->exit_request = 1;
-    }
-    if (env->exit_request) {
-        env->exit_request = 0;
-        env->exception_index = EXCP_INTERRUPT;
     }
+    ret = EXCP_INTERRUPT;
 
+out:
+    env->exit_request = 0;
+    cpu_single_env = NULL;
     return ret;
 }
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ba183c4..377a0a3 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1502,12 +1502,13 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 
 int kvm_arch_process_irqchip_events(CPUState *env)
 {
+    if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+        env->halted = 0;
+    }
     if (env->interrupt_request & CPU_INTERRUPT_INIT) {
         kvm_cpu_synchronize_state(env);
         do_cpu_init(env);
-        env->exception_index = EXCP_HALTED;
     }
-
     if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
         kvm_cpu_synchronize_state(env);
         do_cpu_sipi(env);
@@ -1522,7 +1523,6 @@ static int kvm_handle_halt(CPUState *env)
           (env->eflags & IF_MASK)) &&
         !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
         env->halted = 1;
-        env->exception_index = EXCP_HLT;
         return 0;
     }
 
commit 83f338f73ecb88cc6f85d6e7b81ebef112ce07be
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:17 2011 +0100

    Move debug exception handling out of cpu_exec
    
    To prepare splitting up KVM and TCG CPU entry/exit, move the debug
    exception into cpus.c and invoke cpu_handle_debug_exception on return
    from qemu_cpu_exec.
    
    This also allows to clean up the debug request signaling: We can assign
    the job of informing main-loop to qemu_system_debug_request and stop the
    calling cpu directly in cpu_handle_debug_exception. That means a debug
    stop will now only be signaled via debug_requested and not additionally
    via vmstop_requested.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 8c9fb8b..9c0b10d 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -196,28 +196,6 @@ static inline TranslationBlock *tb_find_fast(void)
     return tb;
 }
 
-static CPUDebugExcpHandler *debug_excp_handler;
-
-CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
-{
-    CPUDebugExcpHandler *old_handler = debug_excp_handler;
-
-    debug_excp_handler = handler;
-    return old_handler;
-}
-
-static void cpu_handle_debug_exception(CPUState *env)
-{
-    CPUWatchpoint *wp;
-
-    if (!env->watchpoint_hit)
-        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
-            wp->flags &= ~BP_WATCHPOINT_HIT;
-
-    if (debug_excp_handler)
-        debug_excp_handler(env);
-}
-
 /* main execution loop */
 
 volatile sig_atomic_t exit_request;
@@ -287,8 +265,6 @@ int cpu_exec(CPUState *env1)
                 if (env->exception_index >= EXCP_INTERRUPT) {
                     /* exit request from the cpu execution loop */
                     ret = env->exception_index;
-                    if (ret == EXCP_DEBUG)
-                        cpu_handle_debug_exception(env);
                     break;
                 } else {
 #if defined(CONFIG_USER_ONLY)
diff --git a/cpus.c b/cpus.c
index 97a6d4f..c7e86c2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -165,10 +165,34 @@ static bool all_cpu_threads_idle(void)
     return true;
 }
 
-static void cpu_debug_handler(CPUState *env)
+static CPUDebugExcpHandler *debug_excp_handler;
+
+CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
+{
+    CPUDebugExcpHandler *old_handler = debug_excp_handler;
+
+    debug_excp_handler = handler;
+    return old_handler;
+}
+
+static void cpu_handle_debug_exception(CPUState *env)
 {
+    CPUWatchpoint *wp;
+
+    if (!env->watchpoint_hit) {
+        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
+            wp->flags &= ~BP_WATCHPOINT_HIT;
+        }
+    }
+    if (debug_excp_handler) {
+        debug_excp_handler(env);
+    }
+
     gdb_set_stop_cpu(env);
     qemu_system_debug_request();
+#ifdef CONFIG_IOTHREAD
+    env->stopped = 1;
+#endif
 }
 
 #ifdef CONFIG_LINUX
@@ -479,7 +503,6 @@ int qemu_init_main_loop(void)
         return ret;
     }
 #endif
-    cpu_set_debug_excp_handler(cpu_debug_handler);
 
     qemu_init_sigbus();
 
@@ -653,8 +676,6 @@ int qemu_init_main_loop(void)
     int ret;
     sigset_t blocked_signals;
 
-    cpu_set_debug_excp_handler(cpu_debug_handler);
-
     qemu_init_sigbus();
 
     blocked_signals = block_io_signals();
@@ -808,7 +829,10 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
 
     while (1) {
         if (cpu_can_run(env)) {
-            qemu_cpu_exec(env);
+            r = qemu_cpu_exec(env);
+            if (r == EXCP_DEBUG) {
+                cpu_handle_debug_exception(env);
+            }
         }
         qemu_kvm_wait_io_event(env);
     }
@@ -1076,6 +1100,7 @@ bool cpu_exec_all(void)
                 qemu_kvm_eat_signals(env);
             }
             if (r == EXCP_DEBUG) {
+                cpu_handle_debug_exception(env);
                 break;
             }
         } else if (env->stop) {
diff --git a/vl.c b/vl.c
index eebe684..b436952 100644
--- a/vl.c
+++ b/vl.c
@@ -1315,7 +1315,7 @@ void qemu_system_powerdown_request(void)
 void qemu_system_debug_request(void)
 {
     debug_requested = 1;
-    vm_stop(VMSTOP_DEBUG);
+    qemu_notify_event();
 }
 
 void qemu_system_vmstop_request(int reason)
commit 8cf71710f068f9c50ce420b1dd4ef71c2f9b2a8d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:16 2011 +0100

    Refactor debug and vmstop request interface
    
    Instead of fiddling with debug_requested and vmstop_requested directly,
    introduce qemu_system_debug_request and turn qemu_system_vmstop_request
    into a public interface. This aligns those services with exiting ones in
    vl.c.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index ca1f01d..97a6d4f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -168,8 +168,7 @@ static bool all_cpu_threads_idle(void)
 static void cpu_debug_handler(CPUState *env)
 {
     gdb_set_stop_cpu(env);
-    debug_requested = VMSTOP_DEBUG;
-    vm_stop(VMSTOP_DEBUG);
+    qemu_system_debug_request();
 }
 
 #ifdef CONFIG_LINUX
@@ -990,12 +989,6 @@ void qemu_notify_event(void)
     qemu_event_increment();
 }
 
-static void qemu_system_vmstop_request(int reason)
-{
-    vmstop_requested = reason;
-    qemu_notify_event();
-}
-
 void cpu_stop_current(void)
 {
     if (cpu_single_env) {
diff --git a/cpus.h b/cpus.h
index 4cadb64..e021126 100644
--- a/cpus.h
+++ b/cpus.h
@@ -11,8 +11,6 @@ void cpu_stop_current(void);
 /* vl.c */
 extern int smp_cores;
 extern int smp_threads;
-extern int debug_requested;
-extern int vmstop_requested;
 void vm_state_notify(int running, int reason);
 bool cpu_exec_all(void);
 void set_numa_modes(void);
diff --git a/sysemu.h b/sysemu.h
index 0628d3d..0a83ab9 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -61,6 +61,8 @@ void cpu_disable_ticks(void);
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
+void qemu_system_debug_request(void);
+void qemu_system_vmstop_request(int reason);
 int qemu_shutdown_requested(void);
 int qemu_reset_requested(void);
 int qemu_powerdown_requested(void);
diff --git a/vl.c b/vl.c
index 6d2d1d3..eebe684 100644
--- a/vl.c
+++ b/vl.c
@@ -1217,8 +1217,8 @@ static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
 static int reset_requested;
 static int shutdown_requested;
 static int powerdown_requested;
-int debug_requested;
-int vmstop_requested;
+static int debug_requested;
+static int vmstop_requested;
 
 int qemu_shutdown_requested(void)
 {
@@ -1312,6 +1312,18 @@ void qemu_system_powerdown_request(void)
     qemu_notify_event();
 }
 
+void qemu_system_debug_request(void)
+{
+    debug_requested = 1;
+    vm_stop(VMSTOP_DEBUG);
+}
+
+void qemu_system_vmstop_request(int reason)
+{
+    vmstop_requested = reason;
+    qemu_notify_event();
+}
+
 void main_loop_wait(int nonblocking)
 {
     IOHandlerRecord *ioh;
@@ -1427,8 +1439,8 @@ static void main_loop(void)
         dev_time += profile_getclock() - ti;
 #endif
 
-        if ((r = qemu_debug_requested())) {
-            vm_stop(r);
+        if (qemu_debug_requested()) {
+            vm_stop(VMSTOP_DEBUG);
         }
         if (qemu_shutdown_requested()) {
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
commit e07bbac542d45cb246f393f343eb3b867fed4de1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 9 16:29:40 2011 +0100

    Improve vm_stop reason declarations
    
    Define and use dedicated constants for vm_stop reasons, they actually
    have nothing to do with the EXCP_* defines used so far. At this chance,
    specify more detailed reasons so that VM state change handlers can
    evaluate them.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 802d15a..ca1f01d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -168,8 +168,8 @@ static bool all_cpu_threads_idle(void)
 static void cpu_debug_handler(CPUState *env)
 {
     gdb_set_stop_cpu(env);
-    debug_requested = EXCP_DEBUG;
-    vm_stop(EXCP_DEBUG);
+    debug_requested = VMSTOP_DEBUG;
+    vm_stop(VMSTOP_DEBUG);
 }
 
 #ifdef CONFIG_LINUX
diff --git a/gdbstub.c b/gdbstub.c
index d6556c9..ed51a8a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2194,14 +2194,14 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
     const char *type;
     int ret;
 
-    if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) ||
-        s->state == RS_INACTIVE || s->state == RS_SYSCALL)
+    if (running || (reason != VMSTOP_DEBUG && reason != VMSTOP_USER) ||
+        s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
         return;
-
+    }
     /* disable single step if it was enable */
     cpu_single_step(env, 0);
 
-    if (reason == EXCP_DEBUG) {
+    if (reason == VMSTOP_DEBUG) {
         if (env->watchpoint_hit) {
             switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
             case BP_MEM_READ:
@@ -2252,7 +2252,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
     gdb_current_syscall_cb = cb;
     s->state = RS_SYSCALL;
 #ifndef CONFIG_USER_ONLY
-    vm_stop(EXCP_DEBUG);
+    vm_stop(VMSTOP_DEBUG);
 #endif
     s->state = RS_IDLE;
     va_start(va, fmt);
@@ -2326,7 +2326,7 @@ static void gdb_read_byte(GDBState *s, int ch)
     if (vm_running) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
-        vm_stop(EXCP_INTERRUPT);
+        vm_stop(VMSTOP_USER);
     } else
 #endif
     {
@@ -2588,7 +2588,7 @@ static void gdb_chr_event(void *opaque, int event)
 {
     switch (event) {
     case CHR_EVENT_OPENED:
-        vm_stop(EXCP_INTERRUPT);
+        vm_stop(VMSTOP_USER);
         gdb_has_xml = 0;
         break;
     default:
@@ -2628,8 +2628,9 @@ static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
 #ifndef _WIN32
 static void gdb_sigterm_handler(int signal)
 {
-    if (vm_running)
-        vm_stop(EXCP_INTERRUPT);
+    if (vm_running) {
+        vm_stop(VMSTOP_USER);
+    }
 }
 #endif
 
diff --git a/hw/ide/core.c b/hw/ide/core.c
index dd63664..9c91a49 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -465,7 +465,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
         s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
         s->bus->dma->ops->add_status(s->bus->dma, op);
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(0);
+        vm_stop(VMSTOP_DISKFULL);
     } else {
         if (op & BM_STATUS_DMA_RETRY) {
             dma_buf_commit(s, 0);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 488eedd..b05e654 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -239,7 +239,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
         r->status |= SCSI_REQ_STATUS_RETRY | type;
 
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(0);
+        vm_stop(VMSTOP_DISKFULL);
     } else {
         if (type == SCSI_REQ_STATUS_RETRY_READ) {
             r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index ffac5a4..b14fb99 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -78,7 +78,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
         req->next = s->rq;
         s->rq = req;
         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
-        vm_stop(0);
+        vm_stop(VMSTOP_DISKFULL);
     } else {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
         bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
diff --git a/hw/watchdog.c b/hw/watchdog.c
index e9dd56e..1c900a1 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -132,7 +132,7 @@ void watchdog_perform_action(void)
 
     case WDT_PAUSE:             /* same as 'stop' command in monitor */
         watchdog_mon_event("pause");
-        vm_stop(0);
+        vm_stop(VMSTOP_WATCHDOG);
         break;
 
     case WDT_DEBUG:
diff --git a/kvm-all.c b/kvm-all.c
index 42dfed8..19cf188 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -994,7 +994,7 @@ int kvm_cpu_exec(CPUState *env)
 
     if (ret < 0) {
         cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-        vm_stop(0);
+        vm_stop(VMSTOP_PANIC);
         env->exit_request = 1;
     }
     if (env->exit_request) {
diff --git a/migration.c b/migration.c
index 3612572..af3a1f2 100644
--- a/migration.c
+++ b/migration.c
@@ -378,7 +378,7 @@ void migrate_fd_put_ready(void *opaque)
         int old_vm_running = vm_running;
 
         DPRINTF("done iterating\n");
-        vm_stop(0);
+        vm_stop(VMSTOP_MIGRATE);
 
         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
             if (old_vm_running) {
diff --git a/monitor.c b/monitor.c
index 7fc311d..22ae3bb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1255,7 +1255,7 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
  */
 static int do_stop(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    vm_stop(EXCP_INTERRUPT);
+    vm_stop(VMSTOP_USER);
     return 0;
 }
 
@@ -2783,7 +2783,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
     int saved_vm_running  = vm_running;
     const char *name = qdict_get_str(qdict, "name");
 
-    vm_stop(0);
+    vm_stop(VMSTOP_LOADVM);
 
     if (load_vmstate(name) == 0 && saved_vm_running) {
         vm_start();
diff --git a/savevm.c b/savevm.c
index 6d83b0f..a50fd31 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1575,7 +1575,7 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
     int ret;
 
     saved_vm_running = vm_running;
-    vm_stop(0);
+    vm_stop(VMSTOP_SAVEVM);
 
     if (qemu_savevm_state_blocked(mon)) {
         ret = -EINVAL;
@@ -1904,7 +1904,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     }
 
     saved_vm_running = vm_running;
-    vm_stop(0);
+    vm_stop(VMSTOP_SAVEVM);
 
     memset(sn, 0, sizeof(*sn));
 
diff --git a/sysemu.h b/sysemu.h
index 23ae17e..0628d3d 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -37,6 +37,16 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
                                                      void *opaque);
 void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
 
+#define VMSTOP_USER      0
+#define VMSTOP_DEBUG     1
+#define VMSTOP_SHUTDOWN  2
+#define VMSTOP_DISKFULL  3
+#define VMSTOP_WATCHDOG  4
+#define VMSTOP_PANIC     5
+#define VMSTOP_SAVEVM    6
+#define VMSTOP_LOADVM    7
+#define VMSTOP_MIGRATE   8
+
 void vm_start(void);
 void vm_stop(int reason);
 
diff --git a/vl.c b/vl.c
index c9fa266..6d2d1d3 100644
--- a/vl.c
+++ b/vl.c
@@ -1433,7 +1433,7 @@ static void main_loop(void)
         if (qemu_shutdown_requested()) {
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
             if (no_shutdown) {
-                vm_stop(0);
+                vm_stop(VMSTOP_SHUTDOWN);
                 no_shutdown = 0;
             } else
                 break;
commit 0ab07c623c629acfbc792e5a174129c19faefbb7
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:14 2011 +0100

    Fix a few coding style violations in cpus.c
    
    No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index e963208..802d15a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -130,10 +130,12 @@ static void do_vm_stop(int reason)
 
 static int cpu_can_run(CPUState *env)
 {
-    if (env->stop)
+    if (env->stop) {
         return 0;
-    if (env->stopped || !vm_running)
+    }
+    if (env->stopped || !vm_running) {
         return 0;
+    }
     return 1;
 }
 
@@ -225,9 +227,9 @@ static void qemu_event_increment(void)
     static const uint64_t val = 1;
     ssize_t ret;
 
-    if (io_thread_fd == -1)
+    if (io_thread_fd == -1) {
         return;
-
+    }
     do {
         ret = write(io_thread_fd, &val, sizeof(val));
     } while (ret < 0 && errno == EINTR);
@@ -258,17 +260,17 @@ static int qemu_event_init(void)
     int fds[2];
 
     err = qemu_eventfd(fds);
-    if (err == -1)
+    if (err == -1) {
         return -errno;
-
+    }
     err = fcntl_setfl(fds[0], O_NONBLOCK);
-    if (err < 0)
+    if (err < 0) {
         goto fail;
-
+    }
     err = fcntl_setfl(fds[1], O_NONBLOCK);
-    if (err < 0)
+    if (err < 0) {
         goto fail;
-
+    }
     qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
                          (void *)(unsigned long)fds[0]);
 
@@ -527,7 +529,6 @@ void pause_all_vcpus(void)
 
 void qemu_cpu_kick(void *env)
 {
-    return;
 }
 
 void qemu_cpu_kick_self(void)
@@ -660,13 +661,15 @@ int qemu_init_main_loop(void)
     blocked_signals = block_io_signals();
 
     ret = qemu_signalfd_init(blocked_signals);
-    if (ret)
+    if (ret) {
         return ret;
+    }
 
     /* Note eventfd must be drained before signalfd handlers run */
     ret = qemu_event_init();
-    if (ret)
+    if (ret) {
         return ret;
+    }
 
     qemu_cond_init(&qemu_pause_cond);
     qemu_cond_init(&qemu_system_cond);
@@ -696,10 +699,11 @@ void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 
     wi.func = func;
     wi.data = data;
-    if (!env->queued_work_first)
+    if (!env->queued_work_first) {
         env->queued_work_first = &wi;
-    else
+    } else {
         env->queued_work_last->next = &wi;
+    }
     env->queued_work_last = &wi;
     wi.next = NULL;
     wi.done = false;
@@ -717,8 +721,9 @@ static void flush_queued_work(CPUState *env)
 {
     struct qemu_work_item *wi;
 
-    if (!env->queued_work_first)
+    if (!env->queued_work_first) {
         return;
+    }
 
     while ((wi = env->queued_work_first)) {
         env->queued_work_first = wi->next;
@@ -798,12 +803,14 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     qemu_cond_signal(&qemu_cpu_cond);
 
     /* and wait for machine initialization */
-    while (!qemu_system_ready)
+    while (!qemu_system_ready) {
         qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+    }
 
     while (1) {
-        if (cpu_can_run(env))
+        if (cpu_can_run(env)) {
             qemu_cpu_exec(env);
+        }
         qemu_kvm_wait_io_event(env);
     }
 
@@ -819,13 +826,15 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     /* signal CPU creation */
     qemu_mutex_lock(&qemu_global_mutex);
-    for (env = first_cpu; env != NULL; env = env->next_cpu)
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
         env->created = 1;
+    }
     qemu_cond_signal(&qemu_cpu_cond);
 
     /* and wait for machine initialization */
-    while (!qemu_system_ready)
+    while (!qemu_system_ready) {
         qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+    }
 
     while (1) {
         cpu_exec_all();
@@ -838,6 +847,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 void qemu_cpu_kick(void *_env)
 {
     CPUState *env = _env;
+
     qemu_cond_broadcast(env->halt_cond);
     if (!env->thread_kicked) {
         qemu_thread_signal(env->thread, SIG_IPI);
@@ -889,8 +899,9 @@ static int all_vcpus_paused(void)
     CPUState *penv = first_cpu;
 
     while (penv) {
-        if (!penv->stopped)
+        if (!penv->stopped) {
             return 0;
+        }
         penv = (CPUState *)penv->next_cpu;
     }
 
@@ -932,14 +943,16 @@ void resume_all_vcpus(void)
 static void qemu_tcg_init_vcpu(void *_env)
 {
     CPUState *env = _env;
+
     /* share a single thread for all cpus with TCG */
     if (!tcg_cpu_thread) {
         env->thread = qemu_mallocz(sizeof(QemuThread));
         env->halt_cond = qemu_mallocz(sizeof(QemuCond));
         qemu_cond_init(env->halt_cond);
         qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
-        while (env->created == 0)
+        while (env->created == 0) {
             qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+        }
         tcg_cpu_thread = env->thread;
         tcg_halt_cond = env->halt_cond;
     } else {
@@ -954,8 +967,9 @@ static void qemu_kvm_start_vcpu(CPUState *env)
     env->halt_cond = qemu_mallocz(sizeof(QemuCond));
     qemu_cond_init(env->halt_cond);
     qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
-    while (env->created == 0)
+    while (env->created == 0) {
         qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+    }
 }
 
 void qemu_init_vcpu(void *_env)
@@ -964,10 +978,11 @@ void qemu_init_vcpu(void *_env)
 
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
-    if (kvm_enabled())
+    if (kvm_enabled()) {
         qemu_kvm_start_vcpu(env);
-    else
+    } else {
         qemu_tcg_init_vcpu(env);
+    }
 }
 
 void qemu_notify_event(void)
@@ -1050,16 +1065,18 @@ bool cpu_exec_all(void)
 {
     int r;
 
-    if (next_cpu == NULL)
+    if (next_cpu == NULL) {
         next_cpu = first_cpu;
+    }
     for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
         CPUState *env = next_cpu;
 
         qemu_clock_enable(vm_clock,
                           (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
 
-        if (qemu_alarm_pending())
+        if (qemu_alarm_pending()) {
             break;
+        }
         if (cpu_can_run(env)) {
             r = qemu_cpu_exec(env);
             if (kvm_enabled()) {
commit 164003228347eb0c27ab6c0e80e2753df55cdbc5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Feb 9 16:29:37 2011 +0100

    Refactor cpu_has_work/any_cpu_has_work in cpus.c
    
    Avoid duplicate use of the function name cpu_has_work, it's confusing,
    also their scope. Refactor cpu_has_work to cpu_thread_is_idle and do the
    same with any_cpu_has_work.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index d54ec7d..e963208 100644
--- a/cpus.c
+++ b/cpus.c
@@ -137,29 +137,30 @@ static int cpu_can_run(CPUState *env)
     return 1;
 }
 
-static int cpu_has_work(CPUState *env)
+static bool cpu_thread_is_idle(CPUState *env)
 {
-    if (env->stop)
-        return 1;
-    if (env->queued_work_first)
-        return 1;
-    if (env->stopped || !vm_running)
-        return 0;
-    if (!env->halted)
-        return 1;
-    if (qemu_cpu_has_work(env))
-        return 1;
-    return 0;
+    if (env->stop || env->queued_work_first) {
+        return false;
+    }
+    if (env->stopped || !vm_running) {
+        return true;
+    }
+    if (!env->halted || qemu_cpu_has_work(env)) {
+        return false;
+    }
+    return true;
 }
 
-static int any_cpu_has_work(void)
+static bool all_cpu_threads_idle(void)
 {
     CPUState *env;
 
-    for (env = first_cpu; env != NULL; env = env->next_cpu)
-        if (cpu_has_work(env))
-            return 1;
-    return 0;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        if (!cpu_thread_is_idle(env)) {
+            return false;
+        }
+    }
+    return true;
 }
 
 static void cpu_debug_handler(CPUState *env)
@@ -743,8 +744,9 @@ static void qemu_tcg_wait_io_event(void)
 {
     CPUState *env;
 
-    while (!any_cpu_has_work())
+    while (all_cpu_threads_idle()) {
         qemu_cond_timedwait(tcg_halt_cond, &qemu_global_mutex, 1000);
+    }
 
     qemu_mutex_unlock(&qemu_global_mutex);
 
@@ -765,8 +767,9 @@ static void qemu_tcg_wait_io_event(void)
 
 static void qemu_kvm_wait_io_event(CPUState *env)
 {
-    while (!cpu_has_work(env))
+    while (cpu_thread_is_idle(env)) {
         qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+    }
 
     qemu_kvm_eat_signals(env);
     qemu_wait_io_event_common(env);
@@ -1070,7 +1073,7 @@ bool cpu_exec_all(void)
         }
     }
     exit_request = 0;
-    return any_cpu_has_work();
+    return !all_cpu_threads_idle();
 }
 
 void set_numa_modes(void)
commit 7e97cd88148876bad36ee7c66d526dcaed328d0d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Feb 7 12:19:12 2011 +0100

    Refactor kvm&tcg function names in cpus.c
    
    Pure interface cosmetics: Ensure that only kvm core services (as
    declared in kvm.h) start with "kvm_". Prepend "qemu_" to those that
    violate this rule in cpus.c. Also rename the corresponding tcg functions
    for the sake of consistency.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 6a85dc8..d54ec7d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -774,7 +774,7 @@ static void qemu_kvm_wait_io_event(CPUState *env)
 
 static int qemu_cpu_exec(CPUState *env);
 
-static void *kvm_cpu_thread_fn(void *arg)
+static void *qemu_kvm_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
     int r;
@@ -807,7 +807,7 @@ static void *kvm_cpu_thread_fn(void *arg)
     return NULL;
 }
 
-static void *tcg_cpu_thread_fn(void *arg)
+static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
@@ -926,7 +926,7 @@ void resume_all_vcpus(void)
     }
 }
 
-static void tcg_init_vcpu(void *_env)
+static void qemu_tcg_init_vcpu(void *_env)
 {
     CPUState *env = _env;
     /* share a single thread for all cpus with TCG */
@@ -934,7 +934,7 @@ static void tcg_init_vcpu(void *_env)
         env->thread = qemu_mallocz(sizeof(QemuThread));
         env->halt_cond = qemu_mallocz(sizeof(QemuCond));
         qemu_cond_init(env->halt_cond);
-        qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
+        qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
         while (env->created == 0)
             qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
         tcg_cpu_thread = env->thread;
@@ -945,12 +945,12 @@ static void tcg_init_vcpu(void *_env)
     }
 }
 
-static void kvm_start_vcpu(CPUState *env)
+static void qemu_kvm_start_vcpu(CPUState *env)
 {
     env->thread = qemu_mallocz(sizeof(QemuThread));
     env->halt_cond = qemu_mallocz(sizeof(QemuCond));
     qemu_cond_init(env->halt_cond);
-    qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
+    qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
     while (env->created == 0)
         qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
 }
@@ -962,9 +962,9 @@ void qemu_init_vcpu(void *_env)
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
     if (kvm_enabled())
-        kvm_start_vcpu(env);
+        qemu_kvm_start_vcpu(env);
     else
-        tcg_init_vcpu(env);
+        qemu_tcg_init_vcpu(env);
 }
 
 void qemu_notify_event(void)
commit b8cc45d6a6f7b6607d5c55817d674f3e5f92ff70
Author: Glauber Costa <glommer at redhat.com>
Date:   Thu Feb 3 14:19:53 2011 -0500

    kvm: make tsc stable over migration and machine start
    
    If the machine is stopped, we should not record two different tsc values
    upon a save operation. The same problem happens with kvmclock.
    
    But kvmclock is taking a different diretion, being now seen as a separate
    device. Since this is unlikely to happen with the tsc, I am taking the
    approach here of simply registering a handler for state change, and
    using a per-CPUState variable that prevents double updates for the TSC.
    
    Signed-off-by: Glauber Costa <glommer at redhat.com>
    CC: Jan Kiszka <jan.kiszka at web.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index af701a4..5f1df8b 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -734,6 +734,7 @@ typedef struct CPUX86State {
     uint32_t sipi_vector;
     uint32_t cpuid_kvm_features;
     uint32_t cpuid_svm_features;
+    bool tsc_valid;
     
     /* in order to simplify APIC support, we leave this pointer to the
        user */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 8a87244..ba183c4 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -301,6 +301,15 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
 #endif
 }
 
+static void cpu_update_state(void *opaque, int running, int reason)
+{
+    CPUState *env = opaque;
+
+    if (running) {
+        env->tsc_valid = false;
+    }
+}
+
 int kvm_arch_init_vcpu(CPUState *env)
 {
     struct {
@@ -434,6 +443,8 @@ int kvm_arch_init_vcpu(CPUState *env)
     }
 #endif
 
+    qemu_add_vm_change_state_handler(cpu_update_state, env);
+
     return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
 }
 
@@ -1061,7 +1072,12 @@ static int kvm_get_msrs(CPUState *env)
     if (has_msr_hsave_pa) {
         msrs[n++].index = MSR_VM_HSAVE_PA;
     }
-    msrs[n++].index = MSR_IA32_TSC;
+
+    if (!env->tsc_valid) {
+        msrs[n++].index = MSR_IA32_TSC;
+        env->tsc_valid = !vm_running;
+    }
+
 #ifdef TARGET_X86_64
     if (lm_capable_kernel) {
         msrs[n++].index = MSR_CSTAR;
commit cdea50ede1b8a2efe989fafc57260053b180219f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:16:02 2011 +0100

    kvm: Leave kvm_cpu_exec directly after KVM_EXIT_SHUTDOWN
    
    The reset we issue on KVM_EXIT_SHUTDOWN implies that we should also
    leave the VCPU loop. As we now check for exit_request which is set by
    qemu_system_reset_request, this bug is no longer critical. Still it's an
    unneeded extra turn.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 4729ec5..42dfed8 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -963,7 +963,6 @@ int kvm_cpu_exec(CPUState *env)
         case KVM_EXIT_SHUTDOWN:
             DPRINTF("shutdown\n");
             qemu_system_reset_request();
-            ret = 1;
             break;
         case KVM_EXIT_UNKNOWN:
             fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
commit b30e93e9ec01c87d53fb0c777e4b0fa258e85ca8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:16:01 2011 +0100

    kvm: Remove static return code of kvm_handle_io
    
    Improve the readability of the exit dispatcher by moving the static
    return value of kvm_handle_io to its caller.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 0c20f9e..4729ec5 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -774,8 +774,8 @@ err:
     return ret;
 }
 
-static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
-                         uint32_t count)
+static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
+                          uint32_t count)
 {
     int i;
     uint8_t *ptr = data;
@@ -809,8 +809,6 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
 
         ptr += size;
     }
-
-    return 1;
 }
 
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
@@ -944,11 +942,12 @@ int kvm_cpu_exec(CPUState *env)
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
             DPRINTF("handle_io\n");
-            ret = kvm_handle_io(run->io.port,
-                                (uint8_t *)run + run->io.data_offset,
-                                run->io.direction,
-                                run->io.size,
-                                run->io.count);
+            kvm_handle_io(run->io.port,
+                          (uint8_t *)run + run->io.data_offset,
+                          run->io.direction,
+                          run->io.size,
+                          run->io.count);
+            ret = 1;
             break;
         case KVM_EXIT_MMIO:
             DPRINTF("handle_mmio\n");
commit 9ccfac9ea4b862a75a4270ed32db1f8e314911c5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:16:00 2011 +0100

    kvm: Unconditionally reenter kernel after IO exits
    
    KVM requires to reenter the kernel after IO exits in order to complete
    instruction emulation. Failing to do so will leave the kernel state
    inconsistently behind. To ensure that we will get back ASAP, we issue a
    self-signal that will cause KVM_RUN to return once the pending
    operations are completed.
    
    We can move kvm_arch_process_irqchip_events out of the inner VCPU loop.
    The only state that mattered at its old place was a pending INIT
    request. Catch it in kvm_arch_pre_run and also trigger a self-signal to
    process the request on next kvm_cpu_exec.
    
    This patch also fixes the missing exit_request check in kvm_cpu_exec in
    the CONFIG_IOTHREAD case.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index a83aff2..0c20f9e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -199,7 +199,6 @@ int kvm_pit_in_kernel(void)
     return kvm_state->pit_in_kernel;
 }
 
-
 int kvm_init_vcpu(CPUState *env)
 {
     KVMState *s = kvm_state;
@@ -896,29 +895,33 @@ int kvm_cpu_exec(CPUState *env)
 
     DPRINTF("kvm_cpu_exec()\n");
 
-    do {
-#ifndef CONFIG_IOTHREAD
-        if (env->exit_request) {
-            DPRINTF("interrupt exit requested\n");
-            ret = 0;
-            break;
-        }
-#endif
-
-        if (kvm_arch_process_irqchip_events(env)) {
-            ret = 0;
-            break;
-        }
+    if (kvm_arch_process_irqchip_events(env)) {
+        env->exit_request = 0;
+        env->exception_index = EXCP_HLT;
+        return 0;
+    }
 
+    do {
         if (env->kvm_vcpu_dirty) {
             kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
             env->kvm_vcpu_dirty = 0;
         }
 
         kvm_arch_pre_run(env, run);
+        if (env->exit_request) {
+            DPRINTF("interrupt exit requested\n");
+            /*
+             * KVM requires us to reenter the kernel after IO exits to complete
+             * instruction emulation. This self-signal will ensure that we
+             * leave ASAP again.
+             */
+            qemu_cpu_kick_self();
+        }
         cpu_single_env = NULL;
         qemu_mutex_unlock_iothread();
+
         ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
+
         qemu_mutex_lock_iothread();
         cpu_single_env = env;
         kvm_arch_post_run(env, run);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9df8ff8..8a87244 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1426,6 +1426,11 @@ int kvm_arch_get_registers(CPUState *env)
 
 int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
+    /* Force the VCPU out of its inner loop to process the INIT request */
+    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+        env->exit_request = 1;
+    }
+
     /* Inject NMI */
     if (env->interrupt_request & CPU_INTERRUPT_NMI) {
         env->interrupt_request &= ~CPU_INTERRUPT_NMI;
commit 46d62fac8a6a43453322b3305ab2fcb8ee594443
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:59 2011 +0100

    Introduce VCPU self-signaling service
    
    Introduce qemu_cpu_kick_self to send SIG_IPI to the calling VCPU
    context. First user will be kvm.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 9a3fc31..6a85dc8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -529,6 +529,17 @@ void qemu_cpu_kick(void *env)
     return;
 }
 
+void qemu_cpu_kick_self(void)
+{
+#ifndef _WIN32
+    assert(cpu_single_env);
+
+    raise(SIG_IPI);
+#else
+    abort();
+#endif
+}
+
 void qemu_notify_event(void)
 {
     CPUState *env = cpu_single_env;
@@ -831,6 +842,16 @@ void qemu_cpu_kick(void *_env)
     }
 }
 
+void qemu_cpu_kick_self(void)
+{
+    assert(cpu_single_env);
+
+    if (!cpu_single_env->thread_kicked) {
+        qemu_thread_signal(cpu_single_env->thread, SIG_IPI);
+        cpu_single_env->thread_kicked = true;
+    }
+}
+
 int qemu_cpu_self(void *_env)
 {
     CPUState *env = _env;
diff --git a/qemu-common.h b/qemu-common.h
index c7ff280..a4d9c21 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -288,6 +288,7 @@ void qemu_notify_event(void);
 
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
+void qemu_cpu_kick_self(void);
 int qemu_cpu_self(void *env);
 
 /* work queue */
commit 6d9cb73c1bf80bfb0b8e7b2b3a23703e621c1405
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:58 2011 +0100

    kvm: Add MCE signal support for !CONFIG_IOTHREAD
    
    Currently, we only configure and process MCE-related SIGBUS events if
    CONFIG_IOTHREAD is enabled. The groundwork is laid, we just need to
    factor out the required handler registration and system configuration.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Huang Ying <ying.huang at intel.com>
    CC: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
    CC: Jin Dongming <jin.dongming at np.css.fujitsu.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 38dd506..9a3fc31 100644
--- a/cpus.c
+++ b/cpus.c
@@ -34,9 +34,6 @@
 
 #include "cpus.h"
 #include "compatfd.h"
-#ifdef CONFIG_LINUX
-#include <sys/prctl.h>
-#endif
 
 #ifdef SIGRTMIN
 #define SIG_IPI (SIGRTMIN+4)
@@ -44,10 +41,24 @@
 #define SIG_IPI SIGUSR1
 #endif
 
+#ifdef CONFIG_LINUX
+
+#include <sys/prctl.h>
+
 #ifndef PR_MCE_KILL
 #define PR_MCE_KILL 33
 #endif
 
+#ifndef PR_MCE_KILL_SET
+#define PR_MCE_KILL_SET 1
+#endif
+
+#ifndef PR_MCE_KILL_EARLY
+#define PR_MCE_KILL_EARLY 1
+#endif
+
+#endif /* CONFIG_LINUX */
+
 static CPUState *next_cpu;
 
 /***********************************************************/
@@ -158,6 +169,52 @@ static void cpu_debug_handler(CPUState *env)
     vm_stop(EXCP_DEBUG);
 }
 
+#ifdef CONFIG_LINUX
+static void sigbus_reraise(void)
+{
+    sigset_t set;
+    struct sigaction action;
+
+    memset(&action, 0, sizeof(action));
+    action.sa_handler = SIG_DFL;
+    if (!sigaction(SIGBUS, &action, NULL)) {
+        raise(SIGBUS);
+        sigemptyset(&set);
+        sigaddset(&set, SIGBUS);
+        sigprocmask(SIG_UNBLOCK, &set, NULL);
+    }
+    perror("Failed to re-raise SIGBUS!\n");
+    abort();
+}
+
+static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
+                           void *ctx)
+{
+    if (kvm_on_sigbus(siginfo->ssi_code,
+                      (void *)(intptr_t)siginfo->ssi_addr)) {
+        sigbus_reraise();
+    }
+}
+
+static void qemu_init_sigbus(void)
+{
+    struct sigaction action;
+
+    memset(&action, 0, sizeof(action));
+    action.sa_flags = SA_SIGINFO;
+    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
+    sigaction(SIGBUS, &action, NULL);
+
+    prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
+}
+
+#else /* !CONFIG_LINUX */
+
+static void qemu_init_sigbus(void)
+{
+}
+#endif /* !CONFIG_LINUX */
+
 #ifndef _WIN32
 static int io_thread_fd = -1;
 
@@ -280,8 +337,6 @@ static int qemu_signalfd_init(sigset_t mask)
     return 0;
 }
 
-static void sigbus_reraise(void);
-
 static void qemu_kvm_eat_signals(CPUState *env)
 {
     struct timespec ts = { 0, 0 };
@@ -302,13 +357,11 @@ static void qemu_kvm_eat_signals(CPUState *env)
         }
 
         switch (r) {
-#ifdef CONFIG_IOTHREAD
         case SIGBUS:
             if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
                 sigbus_reraise();
             }
             break;
-#endif
         default:
             break;
         }
@@ -397,6 +450,7 @@ static sigset_t block_synchronous_signals(void)
     sigset_t set;
 
     sigemptyset(&set);
+    sigaddset(&set, SIGBUS);
     if (kvm_enabled()) {
         /*
          * We need to process timer signals synchronously to avoid a race
@@ -425,6 +479,8 @@ int qemu_init_main_loop(void)
 #endif
     cpu_set_debug_excp_handler(cpu_debug_handler);
 
+    qemu_init_sigbus();
+
     return qemu_event_init();
 }
 
@@ -561,13 +617,9 @@ static void qemu_tcg_init_cpu_signals(void)
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 }
 
-static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
-                           void *ctx);
-
 static sigset_t block_io_signals(void)
 {
     sigset_t set;
-    struct sigaction action;
 
     /* SIGUSR2 used by posix-aio-compat.c */
     sigemptyset(&set);
@@ -581,12 +633,6 @@ static sigset_t block_io_signals(void)
     sigaddset(&set, SIGBUS);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 
-    memset(&action, 0, sizeof(action));
-    action.sa_flags = SA_SIGINFO;
-    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
-    sigaction(SIGBUS, &action, NULL);
-    prctl(PR_MCE_KILL, 1, 1, 0, 0);
-
     return set;
 }
 
@@ -597,6 +643,8 @@ int qemu_init_main_loop(void)
 
     cpu_set_debug_excp_handler(cpu_debug_handler);
 
+    qemu_init_sigbus();
+
     blocked_signals = block_io_signals();
 
     ret = qemu_signalfd_init(blocked_signals);
@@ -704,31 +752,6 @@ static void qemu_tcg_wait_io_event(void)
     }
 }
 
-static void sigbus_reraise(void)
-{
-    sigset_t set;
-    struct sigaction action;
-
-    memset(&action, 0, sizeof(action));
-    action.sa_handler = SIG_DFL;
-    if (!sigaction(SIGBUS, &action, NULL)) {
-        raise(SIGBUS);
-        sigemptyset(&set);
-        sigaddset(&set, SIGBUS);
-        sigprocmask(SIG_UNBLOCK, &set, NULL);
-    }
-    perror("Failed to re-raise SIGBUS!\n");
-    abort();
-}
-
-static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
-                           void *ctx)
-{
-    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr)) {
-        sigbus_reraise();
-    }
-}
-
 static void qemu_kvm_wait_io_event(CPUState *env)
 {
     while (!cpu_has_work(env))
commit de758970b60f129ed9d024cc5c90c1f57fab2fd4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:57 2011 +0100

    kvm: Fix race between timer signals and vcpu entry under !IOTHREAD
    
    Found by Stefan Hajnoczi: There is a race in kvm_cpu_exec between
    checking for exit_request on vcpu entry and timer signals arriving
    before KVM starts to catch them. Plug it by blocking both timer related
    signals also on !CONFIG_IOTHREAD and process those via signalfd.
    
    As this fix depends on real signalfd support (otherwise the timer
    signals only kick the compat helper thread, and the main thread hangs),
    we need to detect the invalid constellation and abort configure.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/configure b/configure
index 598e8e1..a3f5345 100755
--- a/configure
+++ b/configure
@@ -2057,6 +2057,12 @@ EOF
 
 if compile_prog "" "" ; then
   signalfd=yes
+elif test "$kvm" = "yes" -a "$io_thread" != "yes"; then
+  echo
+  echo "ERROR: Host kernel lacks signalfd() support,"
+  echo "but KVM depends on it when the IO thread is disabled."
+  echo
+  exit 1
 fi
 
 # check if eventfd is supported
diff --git a/cpus.c b/cpus.c
index 84792f0..38dd506 100644
--- a/cpus.c
+++ b/cpus.c
@@ -319,6 +319,12 @@ static void qemu_kvm_eat_signals(CPUState *env)
             exit(1);
         }
     } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
+
+#ifndef CONFIG_IOTHREAD
+    if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
+        qemu_notify_event();
+    }
+#endif
 }
 
 #else /* _WIN32 */
@@ -368,11 +374,15 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
 
     sigemptyset(&set);
     sigaddset(&set, SIG_IPI);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 
     pthread_sigmask(SIG_BLOCK, NULL, &set);
     sigdelset(&set, SIG_IPI);
     sigdelset(&set, SIGBUS);
+    sigdelset(&set, SIGIO);
+    sigdelset(&set, SIGALRM);
     r = kvm_set_signal_mask(env, &set);
     if (r) {
         fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
@@ -381,13 +391,32 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
 #endif
 }
 
+#ifndef _WIN32
+static sigset_t block_synchronous_signals(void)
+{
+    sigset_t set;
+
+    sigemptyset(&set);
+    if (kvm_enabled()) {
+        /*
+         * We need to process timer signals synchronously to avoid a race
+         * between exit_request check and KVM vcpu entry.
+         */
+        sigaddset(&set, SIGIO);
+        sigaddset(&set, SIGALRM);
+    }
+
+    return set;
+}
+#endif
+
 int qemu_init_main_loop(void)
 {
 #ifndef _WIN32
     sigset_t blocked_signals;
     int ret;
 
-    sigemptyset(&blocked_signals);
+    blocked_signals = block_synchronous_signals();
 
     ret = qemu_signalfd_init(blocked_signals);
     if (ret) {
commit d0f294cec0ee25461a0a15b889929c5c7dc983cd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:56 2011 +0100

    Set up signalfd under !CONFIG_IOTHREAD
    
    Will be required for SIGBUS handling. For obvious reasons, this will
    remain a nop on Windows hosts.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index adb5842..b21f9d3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -141,7 +141,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y))
 
 common-obj-y += iov.o acl.o
 common-obj-$(CONFIG_THREAD) += qemu-thread.o
-common-obj-$(CONFIG_IOTHREAD) += compatfd.o
+common-obj-$(CONFIG_POSIX) += compatfd.o
 common-obj-y += notify.o event_notifier.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
 
diff --git a/cpus.c b/cpus.c
index f2ec74c..84792f0 100644
--- a/cpus.c
+++ b/cpus.c
@@ -227,6 +227,59 @@ static void dummy_signal(int sig)
 {
 }
 
+/* If we have signalfd, we mask out the signals we want to handle and then
+ * use signalfd to listen for them.  We rely on whatever the current signal
+ * handler is to dispatch the signals when we receive them.
+ */
+static void sigfd_handler(void *opaque)
+{
+    int fd = (unsigned long) opaque;
+    struct qemu_signalfd_siginfo info;
+    struct sigaction action;
+    ssize_t len;
+
+    while (1) {
+        do {
+            len = read(fd, &info, sizeof(info));
+        } while (len == -1 && errno == EINTR);
+
+        if (len == -1 && errno == EAGAIN) {
+            break;
+        }
+
+        if (len != sizeof(info)) {
+            printf("read from sigfd returned %zd: %m\n", len);
+            return;
+        }
+
+        sigaction(info.ssi_signo, NULL, &action);
+        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
+            action.sa_sigaction(info.ssi_signo,
+                                (siginfo_t *)&info, NULL);
+        } else if (action.sa_handler) {
+            action.sa_handler(info.ssi_signo);
+        }
+    }
+}
+
+static int qemu_signalfd_init(sigset_t mask)
+{
+    int sigfd;
+
+    sigfd = qemu_signalfd(&mask);
+    if (sigfd == -1) {
+        fprintf(stderr, "failed to create signalfd\n");
+        return -errno;
+    }
+
+    fcntl_setfl(sigfd, O_NONBLOCK);
+
+    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
+                         (void *)(unsigned long) sigfd);
+
+    return 0;
+}
+
 static void sigbus_reraise(void);
 
 static void qemu_kvm_eat_signals(CPUState *env)
@@ -330,6 +383,17 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
 
 int qemu_init_main_loop(void)
 {
+#ifndef _WIN32
+    sigset_t blocked_signals;
+    int ret;
+
+    sigemptyset(&blocked_signals);
+
+    ret = qemu_signalfd_init(blocked_signals);
+    if (ret) {
+        return ret;
+    }
+#endif
     cpu_set_debug_excp_handler(cpu_debug_handler);
 
     return qemu_event_init();
@@ -426,41 +490,6 @@ static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-/* If we have signalfd, we mask out the signals we want to handle and then
- * use signalfd to listen for them.  We rely on whatever the current signal
- * handler is to dispatch the signals when we receive them.
- */
-static void sigfd_handler(void *opaque)
-{
-    int fd = (unsigned long) opaque;
-    struct qemu_signalfd_siginfo info;
-    struct sigaction action;
-    ssize_t len;
-
-    while (1) {
-        do {
-            len = read(fd, &info, sizeof(info));
-        } while (len == -1 && errno == EINTR);
-
-        if (len == -1 && errno == EAGAIN) {
-            break;
-        }
-
-        if (len != sizeof(info)) {
-            printf("read from sigfd returned %zd: %m\n", len);
-            return;
-        }
-
-        sigaction(info.ssi_signo, NULL, &action);
-        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
-            action.sa_sigaction(info.ssi_signo,
-                                (siginfo_t *)&info, NULL);
-        } else if (action.sa_handler) {
-            action.sa_handler(info.ssi_signo);
-        }
-    }
-}
-
 static void cpu_signal(int sig)
 {
     if (cpu_single_env) {
@@ -532,24 +561,6 @@ static sigset_t block_io_signals(void)
     return set;
 }
 
-static int qemu_signalfd_init(sigset_t mask)
-{
-    int sigfd;
-
-    sigfd = qemu_signalfd(&mask);
-    if (sigfd == -1) {
-        fprintf(stderr, "failed to create signalfd\n");
-        return -errno;
-    }
-
-    fcntl_setfl(sigfd, O_NONBLOCK);
-
-    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
-                         (void *)(unsigned long) sigfd);
-
-    return 0;
-}
-
 int qemu_init_main_loop(void)
 {
     int ret;
commit 9a36085b866002d8e469f46078f0db5201f44999
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:55 2011 +0100

    kvm: Call qemu_kvm_eat_signals also under !CONFIG_IOTHREAD
    
    Move qemu_kvm_eat_signals around and call it also when the IO-thread is
    not used. Do not yet process SIGBUS, will be armed in a separate step.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index d9c9111..f2ec74c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -227,6 +227,47 @@ static void dummy_signal(int sig)
 {
 }
 
+static void sigbus_reraise(void);
+
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+    struct timespec ts = { 0, 0 };
+    siginfo_t siginfo;
+    sigset_t waitset;
+    sigset_t chkset;
+    int r;
+
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIG_IPI);
+    sigaddset(&waitset, SIGBUS);
+
+    do {
+        r = sigtimedwait(&waitset, &siginfo, &ts);
+        if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
+            perror("sigtimedwait");
+            exit(1);
+        }
+
+        switch (r) {
+#ifdef CONFIG_IOTHREAD
+        case SIGBUS:
+            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
+                sigbus_reraise();
+            }
+            break;
+#endif
+        default:
+            break;
+        }
+
+        r = sigpending(&chkset);
+        if (r == -1) {
+            perror("sigpending");
+            exit(1);
+        }
+    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
+}
+
 #else /* _WIN32 */
 
 HANDLE qemu_event_handle;
@@ -254,6 +295,10 @@ static void qemu_event_increment(void)
         exit (1);
     }
 }
+
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+}
 #endif /* _WIN32 */
 
 #ifndef CONFIG_IOTHREAD
@@ -644,43 +689,6 @@ static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
     }
 }
 
-static void qemu_kvm_eat_signals(CPUState *env)
-{
-    struct timespec ts = { 0, 0 };
-    siginfo_t siginfo;
-    sigset_t waitset;
-    sigset_t chkset;
-    int r;
-
-    sigemptyset(&waitset);
-    sigaddset(&waitset, SIG_IPI);
-    sigaddset(&waitset, SIGBUS);
-
-    do {
-        r = sigtimedwait(&waitset, &siginfo, &ts);
-        if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
-            perror("sigtimedwait");
-            exit(1);
-        }
-
-        switch (r) {
-        case SIGBUS:
-            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
-                sigbus_reraise();
-            }
-            break;
-        default:
-            break;
-        }
-
-        r = sigpending(&chkset);
-        if (r == -1) {
-            perror("sigpending");
-            exit(1);
-        }
-    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
-}
-
 static void qemu_kvm_wait_io_event(CPUState *env)
 {
     while (!cpu_has_work(env))
@@ -953,6 +961,8 @@ static int qemu_cpu_exec(CPUState *env)
 
 bool cpu_exec_all(void)
 {
+    int r;
+
     if (next_cpu == NULL)
         next_cpu = first_cpu;
     for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
@@ -964,7 +974,11 @@ bool cpu_exec_all(void)
         if (qemu_alarm_pending())
             break;
         if (cpu_can_run(env)) {
-            if (qemu_cpu_exec(env) == EXCP_DEBUG) {
+            r = qemu_cpu_exec(env);
+            if (kvm_enabled()) {
+                qemu_kvm_eat_signals(env);
+            }
+            if (r == EXCP_DEBUG) {
                 break;
             }
         } else if (env->stop) {
commit 5db5bdacdfb115bb23d57808947f1ec1bcc00ef3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:54 2011 +0100

    kvm: Refactor qemu_kvm_eat_signals
    
    We do not use the timeout, so drop its logic. As we always poll our
    signals, we do not need to drop the global lock. Removing those calls
    allows some further simplifications. Also fix the error processing of
    sigpending at this chance.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index f27dfbd..d9c9111 100644
--- a/cpus.c
+++ b/cpus.c
@@ -644,31 +644,22 @@ static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
     }
 }
 
-static void qemu_kvm_eat_signal(CPUState *env, int timeout)
+static void qemu_kvm_eat_signals(CPUState *env)
 {
-    struct timespec ts;
-    int r, e;
+    struct timespec ts = { 0, 0 };
     siginfo_t siginfo;
     sigset_t waitset;
     sigset_t chkset;
-
-    ts.tv_sec = timeout / 1000;
-    ts.tv_nsec = (timeout % 1000) * 1000000;
+    int r;
 
     sigemptyset(&waitset);
     sigaddset(&waitset, SIG_IPI);
     sigaddset(&waitset, SIGBUS);
 
     do {
-        qemu_mutex_unlock(&qemu_global_mutex);
-
         r = sigtimedwait(&waitset, &siginfo, &ts);
-        e = errno;
-
-        qemu_mutex_lock(&qemu_global_mutex);
-
-        if (r == -1 && !(e == EAGAIN || e == EINTR)) {
-            fprintf(stderr, "sigtimedwait: %s\n", strerror(e));
+        if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
+            perror("sigtimedwait");
             exit(1);
         }
 
@@ -684,7 +675,7 @@ static void qemu_kvm_eat_signal(CPUState *env, int timeout)
 
         r = sigpending(&chkset);
         if (r == -1) {
-            fprintf(stderr, "sigpending: %s\n", strerror(e));
+            perror("sigpending");
             exit(1);
         }
     } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
@@ -695,7 +686,7 @@ static void qemu_kvm_wait_io_event(CPUState *env)
     while (!cpu_has_work(env))
         qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
 
-    qemu_kvm_eat_signal(env, 0);
+    qemu_kvm_eat_signals(env);
     qemu_wait_io_event_common(env);
 }
 
commit ff48eb5fe79ad9ce50127965bd42320c7cccc8a1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:53 2011 +0100

    kvm: Set up signal mask also for !CONFIG_IOTHREAD
    
    Block SIG_IPI, unblock it during KVM_RUN, just like in io-thread mode.
    It's unused so far, but this infrastructure will be required for
    self-IPIs and to process SIGBUS plus, in KVM mode, SIGIO and SIGALRM. As
    Windows doesn't support signal services, we need to provide a stub for
    the init function.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 62120c4..f27dfbd 100644
--- a/cpus.c
+++ b/cpus.c
@@ -223,11 +223,9 @@ fail:
     return err;
 }
 
-#ifdef CONFIG_IOTHREAD
 static void dummy_signal(int sig)
 {
 }
-#endif
 
 #else /* _WIN32 */
 
@@ -259,6 +257,32 @@ static void qemu_event_increment(void)
 #endif /* _WIN32 */
 
 #ifndef CONFIG_IOTHREAD
+static void qemu_kvm_init_cpu_signals(CPUState *env)
+{
+#ifndef _WIN32
+    int r;
+    sigset_t set;
+    struct sigaction sigact;
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = dummy_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
+    sigdelset(&set, SIGBUS);
+    r = kvm_set_signal_mask(env, &set);
+    if (r) {
+        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+        exit(1);
+    }
+#endif
+}
+
 int qemu_init_main_loop(void)
 {
     cpu_set_debug_excp_handler(cpu_debug_handler);
@@ -284,6 +308,7 @@ void qemu_init_vcpu(void *_env)
             fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
             exit(1);
         }
+        qemu_kvm_init_cpu_signals(env);
     }
 }
 
commit 55f8d6ac3e03d2859393c281737f60c65dfc9ab3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:52 2011 +0100

    Refactor signal setup functions in cpus.c
    
    Move {tcg,kvm}_init_ipi and block_io_signals to avoid prototypes, rename
    the former two to clarify that they deal with more than SIG_IPI. No
    functional changes - except for the tiny fixup of strerror usage.
    
    The forward declaration of sigbus_handler is just temporarily, it will
    be moved in a succeeding patch. dummy_signal is moved into the !_WIN32
    block as we will soon need it also for !CONFIG_IOTHREAD.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 4975317..62120c4 100644
--- a/cpus.c
+++ b/cpus.c
@@ -222,7 +222,15 @@ fail:
     close(fds[1]);
     return err;
 }
-#else
+
+#ifdef CONFIG_IOTHREAD
+static void dummy_signal(int sig)
+{
+}
+#endif
+
+#else /* _WIN32 */
+
 HANDLE qemu_event_handle;
 
 static void dummy_event_handler(void *opaque)
@@ -248,7 +256,7 @@ static void qemu_event_increment(void)
         exit (1);
     }
 }
-#endif
+#endif /* _WIN32 */
 
 #ifndef CONFIG_IOTHREAD
 int qemu_init_main_loop(void)
@@ -348,10 +356,6 @@ static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-static void tcg_init_ipi(void);
-static void kvm_init_ipi(CPUState *env);
-static sigset_t block_io_signals(void);
-
 /* If we have signalfd, we mask out the signals we want to handle and then
  * use signalfd to listen for them.  We rely on whatever the current signal
  * handler is to dispatch the signals when we receive them.
@@ -387,6 +391,77 @@ static void sigfd_handler(void *opaque)
     }
 }
 
+static void cpu_signal(int sig)
+{
+    if (cpu_single_env) {
+        cpu_exit(cpu_single_env);
+    }
+    exit_request = 1;
+}
+
+static void qemu_kvm_init_cpu_signals(CPUState *env)
+{
+    int r;
+    sigset_t set;
+    struct sigaction sigact;
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = dummy_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
+    sigdelset(&set, SIGBUS);
+    r = kvm_set_signal_mask(env, &set);
+    if (r) {
+        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+        exit(1);
+    }
+}
+
+static void qemu_tcg_init_cpu_signals(void)
+{
+    sigset_t set;
+    struct sigaction sigact;
+
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = cpu_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+}
+
+static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
+                           void *ctx);
+
+static sigset_t block_io_signals(void)
+{
+    sigset_t set;
+    struct sigaction action;
+
+    /* SIGUSR2 used by posix-aio-compat.c */
+    sigemptyset(&set);
+    sigaddset(&set, SIGUSR2);
+    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIG_IPI);
+    sigaddset(&set, SIGBUS);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    memset(&action, 0, sizeof(action));
+    action.sa_flags = SA_SIGINFO;
+    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
+    sigaction(SIGBUS, &action, NULL);
+    prctl(PR_MCE_KILL, 1, 1, 0, 0);
+
+    return set;
+}
+
 static int qemu_signalfd_init(sigset_t mask)
 {
     int sigfd;
@@ -615,7 +690,7 @@ static void *kvm_cpu_thread_fn(void *arg)
         exit(1);
     }
 
-    kvm_init_ipi(env);
+    qemu_kvm_init_cpu_signals(env);
 
     /* signal CPU creation */
     env->created = 1;
@@ -638,7 +713,7 @@ static void *tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
-    tcg_init_ipi();
+    qemu_tcg_init_cpu_signals();
     qemu_thread_self(env->thread);
 
     /* signal CPU creation */
@@ -679,77 +754,6 @@ int qemu_cpu_self(void *_env)
     return qemu_thread_equal(&this, env->thread);
 }
 
-static void cpu_signal(int sig)
-{
-    if (cpu_single_env)
-        cpu_exit(cpu_single_env);
-    exit_request = 1;
-}
-
-static void tcg_init_ipi(void)
-{
-    sigset_t set;
-    struct sigaction sigact;
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = cpu_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-}
-
-static void dummy_signal(int sig)
-{
-}
-
-static void kvm_init_ipi(CPUState *env)
-{
-    int r;
-    sigset_t set;
-    struct sigaction sigact;
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = dummy_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
-
-    pthread_sigmask(SIG_BLOCK, NULL, &set);
-    sigdelset(&set, SIG_IPI);
-    sigdelset(&set, SIGBUS);
-    r = kvm_set_signal_mask(env, &set);
-    if (r) {
-        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r));
-        exit(1);
-    }
-}
-
-static sigset_t block_io_signals(void)
-{
-    sigset_t set;
-    struct sigaction action;
-
-    /* SIGUSR2 used by posix-aio-compat.c */
-    sigemptyset(&set);
-    sigaddset(&set, SIGUSR2);
-    pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIG_IPI);
-    sigaddset(&set, SIGBUS);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    memset(&action, 0, sizeof(action));
-    action.sa_flags = SA_SIGINFO;
-    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
-    sigaction(SIGBUS, &action, NULL);
-    prctl(PR_MCE_KILL, 1, 1, 0, 0);
-
-    return set;
-}
-
 void qemu_mutex_lock_iothread(void)
 {
     if (kvm_enabled()) {
commit a1b87fe046bbb5a332e51906053c7e0307f26d89
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:51 2011 +0100

    kvm: Provide sigbus services arch-independently
    
    Provide arch-independent kvm_on_sigbus* stubs to remove the #ifdef'ery
    from cpus.c. This patch also fixes --disable-kvm build by providing the
    missing kvm_on_sigbus_vcpu kvm-stub.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 3a72d06..4975317 100644
--- a/cpus.c
+++ b/cpus.c
@@ -539,10 +539,9 @@ static void sigbus_reraise(void)
 static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
                            void *ctx)
 {
-#if defined(TARGET_I386)
-    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr))
-#endif
+    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr)) {
         sigbus_reraise();
+    }
 }
 
 static void qemu_kvm_eat_signal(CPUState *env, int timeout)
@@ -575,10 +574,9 @@ static void qemu_kvm_eat_signal(CPUState *env, int timeout)
 
         switch (r) {
         case SIGBUS:
-#ifdef TARGET_I386
-            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr))
-#endif
+            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
                 sigbus_reraise();
+            }
             break;
         default:
             break;
diff --git a/kvm-all.c b/kvm-all.c
index 55f6ac3..a83aff2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1366,3 +1366,13 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
     return -ENOSYS;
 #endif
 }
+
+int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+{
+    return kvm_arch_on_sigbus_vcpu(env, code, addr);
+}
+
+int kvm_on_sigbus(int code, void *addr)
+{
+    return kvm_arch_on_sigbus(code, addr);
+}
diff --git a/kvm-stub.c b/kvm-stub.c
index 88682f2..d6b6c8e 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -147,6 +147,11 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign)
     return -ENOSYS;
 }
 
+int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+{
+    return 1;
+}
+
 int kvm_on_sigbus(int code, void *addr)
 {
     return 1;
diff --git a/kvm.h b/kvm.h
index ca57517..b2fb5c6 100644
--- a/kvm.h
+++ b/kvm.h
@@ -81,6 +81,9 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset);
 int kvm_pit_in_kernel(void);
 int kvm_irqchip_in_kernel(void);
 
+int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr);
+int kvm_on_sigbus(int code, void *addr);
+
 /* internal API */
 
 struct KVMState;
@@ -121,8 +124,8 @@ int kvm_arch_init_vcpu(CPUState *env);
 
 void kvm_arch_reset_vcpu(CPUState *env);
 
-int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr);
-int kvm_on_sigbus(int code, void *addr);
+int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr);
+int kvm_arch_on_sigbus(int code, void *addr);
 
 struct kvm_guest_debug;
 struct kvm_debug_exit_arch;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 05010bb..9df8ff8 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1839,7 +1839,7 @@ static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
 
 #endif
 
-int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
 {
 #if defined(KVM_CAP_MCE)
     void *vaddr;
@@ -1889,7 +1889,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
     return 0;
 }
 
-int kvm_on_sigbus(int code, void *addr)
+int kvm_arch_on_sigbus(int code, void *addr)
 {
 #if defined(KVM_CAP_MCE)
     if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 710eca1..93ecc57 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -404,3 +404,13 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
 }
+
+int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+{
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    return 1;
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 38823f5..1702c46 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -505,3 +505,13 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
 }
+
+int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
+{
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    return 1;
+}
commit 84b4915dd2c0eaa86c970ffc42a68ea8ba9e48b5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:50 2011 +0100

    kvm: Handle kvm_init_vcpu errors
    
    Do not ignore errors of kvm_init_vcpu, they are fatal.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 8232d44..3a72d06 100644
--- a/cpus.c
+++ b/cpus.c
@@ -265,12 +265,18 @@ void qemu_main_loop_start(void)
 void qemu_init_vcpu(void *_env)
 {
     CPUState *env = _env;
+    int r;
 
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
-    if (kvm_enabled())
-        kvm_init_vcpu(env);
-    return;
+
+    if (kvm_enabled()) {
+        r = kvm_init_vcpu(env);
+        if (r < 0) {
+            fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
+            exit(1);
+        }
+    }
 }
 
 int qemu_cpu_self(void *env)
@@ -600,11 +606,16 @@ static int qemu_cpu_exec(CPUState *env);
 static void *kvm_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
+    int r;
 
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_self(env->thread);
 
-    kvm_init_vcpu(env);
+    r = kvm_init_vcpu(env);
+    if (r < 0) {
+        fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
+        exit(1);
+    }
 
     kvm_init_ipi(env);
 
commit d31ae052a913e8e41a9f22429c28decbdb660568
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:49 2011 +0100

    kvm: Drop redundant kvm_enabled from kvm_cpu_thread_fn
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 0abc009..8232d44 100644
--- a/cpus.c
+++ b/cpus.c
@@ -603,8 +603,8 @@ static void *kvm_cpu_thread_fn(void *arg)
 
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_self(env->thread);
-    if (kvm_enabled())
-        kvm_init_vcpu(env);
+
+    kvm_init_vcpu(env);
 
     kvm_init_ipi(env);
 
commit 748a680b966c65cca9292ba0b9cbb6a04d063b21
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:48 2011 +0100

    kvm: Report proper error on GET_VCPU_MMAP_SIZE failures
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 2ec9e09..55f6ac3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -219,6 +219,7 @@ int kvm_init_vcpu(CPUState *env)
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
     if (mmap_size < 0) {
+        ret = mmap_size;
         DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
         goto err;
     }
commit 46481d3921b86ef5ded7be7b5ce8194608f30e6b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:47 2011 +0100

    Flatten the main loop
    
    First of all, vm_can_run is a misnomer, it actually means "no request
    pending". Moreover, there is no need to check all pending requests
    twice, the first time via the inner loop check and then again when
    actually processing the requests. We can simply remove the inner loop
    and do the checks directly.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/vl.c b/vl.c
index 9c628f0..c9fa266 100644
--- a/vl.c
+++ b/vl.c
@@ -1389,14 +1389,16 @@ void main_loop_wait(int nonblocking)
 
 }
 
-static int vm_can_run(void)
+#ifndef CONFIG_IOTHREAD
+static int vm_request_pending(void)
 {
-    return !(powerdown_requested ||
-             reset_requested ||
-             shutdown_requested ||
-             debug_requested ||
-             vmstop_requested);
+    return powerdown_requested ||
+           reset_requested ||
+           shutdown_requested ||
+           debug_requested ||
+           vmstop_requested;
 }
+#endif
 
 qemu_irq qemu_system_powerdown;
 
@@ -1411,21 +1413,19 @@ static void main_loop(void)
     qemu_main_loop_start();
 
     for (;;) {
-        do {
 #ifndef CONFIG_IOTHREAD
-            nonblocking = cpu_exec_all();
-            if (!vm_can_run()) {
-                nonblocking = true;
-            }
+        nonblocking = cpu_exec_all();
+        if (vm_request_pending()) {
+            nonblocking = true;
+        }
 #endif
 #ifdef CONFIG_PROFILER
-            ti = profile_getclock();
+        ti = profile_getclock();
 #endif
-            main_loop_wait(nonblocking);
+        main_loop_wait(nonblocking);
 #ifdef CONFIG_PROFILER
-            dev_time += profile_getclock() - ti;
+        dev_time += profile_getclock() - ti;
 #endif
-        } while (vm_can_run());
 
         if ((r = qemu_debug_requested())) {
             vm_stop(r);
commit 8e1b90ecc59573c4c5e9fc4934b4e30476b43e2f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:46 2011 +0100

    Leave inner main_loop faster on pending requests
    
    If there is any pending request that requires us to leave the inner loop
    if main_loop, makes sure we do this as soon as possible by enforcing
    non-blocking IO processing.
    
    At this change, move variable definitions out of the inner loop to
    improve readability.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/vl.c b/vl.c
index 30263d6..9c628f0 100644
--- a/vl.c
+++ b/vl.c
@@ -1402,18 +1402,21 @@ qemu_irq qemu_system_powerdown;
 
 static void main_loop(void)
 {
+    bool nonblocking = false;
+#ifdef CONFIG_PROFILER
+    int64_t ti;
+#endif
     int r;
 
     qemu_main_loop_start();
 
     for (;;) {
         do {
-            bool nonblocking = false;
-#ifdef CONFIG_PROFILER
-            int64_t ti;
-#endif
 #ifndef CONFIG_IOTHREAD
             nonblocking = cpu_exec_all();
+            if (!vm_can_run()) {
+                nonblocking = true;
+            }
 #endif
 #ifdef CONFIG_PROFILER
             ti = profile_getclock();
commit 38145df24c55bffe8ba63cfa28173c9ddd5a2c2d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:45 2011 +0100

    Trigger exit from cpu_exec_all on pending IO events
    
    Except for timer events, we currently do not leave the loop over all
    VCPUs if an IO event was filed. That may cause unexpected IO latencies
    under !CONFIG_IOTHREAD in SMP scenarios. Fix it by setting the global
    exit_request which breaks the loop.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index f8a88e3..0abc009 100644
--- a/cpus.c
+++ b/cpus.c
@@ -307,6 +307,7 @@ void qemu_notify_event(void)
     if (next_cpu && env != next_cpu) {
         cpu_exit(next_cpu);
     }
+    exit_request = 1;
 }
 
 void qemu_mutex_lock_iothread(void) {}
commit 1745eaaa7c53c6090d53090d239d0234a7ecfd2d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:44 2011 +0100

    Process vmstop requests in IO thread
    
    A pending vmstop request is also a reason to leave the inner main loop.
    So far we ignored it, and pending stop requests issued over VCPU threads
    were simply ignored.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/vl.c b/vl.c
index 5e3f7f2..30263d6 100644
--- a/vl.c
+++ b/vl.c
@@ -1391,15 +1391,11 @@ void main_loop_wait(int nonblocking)
 
 static int vm_can_run(void)
 {
-    if (powerdown_requested)
-        return 0;
-    if (reset_requested)
-        return 0;
-    if (shutdown_requested)
-        return 0;
-    if (debug_requested)
-        return 0;
-    return 1;
+    return !(powerdown_requested ||
+             reset_requested ||
+             shutdown_requested ||
+             debug_requested ||
+             vmstop_requested);
 }
 
 qemu_irq qemu_system_powerdown;
commit b4a3d965dee06d52281496bb5fd0a5cb5534b545
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:43 2011 +0100

    Stop current VCPU on synchronous reset requests
    
    If some I/O operation ends up calling qemu_system_reset_request in VCPU
    context, we record this and inform the io-thread, but we do not
    terminate the VCPU loop. This can lead to fairly unexpected behavior if
    the triggering reset operation is supposed to work synchronously.
    
    Fix this for TCG (when run in deterministic I/O mode) by setting the
    VCPU on stop and issuing a cpu_exit. KVM requires some more work on its
    VCPU loop.
    
    [ ported from qemu-kvm ]
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index ab6e40e..f8a88e3 100644
--- a/cpus.c
+++ b/cpus.c
@@ -312,6 +312,10 @@ void qemu_notify_event(void)
 void qemu_mutex_lock_iothread(void) {}
 void qemu_mutex_unlock_iothread(void) {}
 
+void cpu_stop_current(void)
+{
+}
+
 void vm_stop(int reason)
 {
     do_vm_stop(reason);
@@ -852,6 +856,14 @@ static void qemu_system_vmstop_request(int reason)
     qemu_notify_event();
 }
 
+void cpu_stop_current(void)
+{
+    if (cpu_single_env) {
+        cpu_single_env->stopped = 1;
+        cpu_exit(cpu_single_env);
+    }
+}
+
 void vm_stop(int reason)
 {
     QemuThread me;
@@ -863,10 +875,7 @@ void vm_stop(int reason)
          * FIXME: should not return to device code in case
          * vm_stop() has been requested.
          */
-        if (cpu_single_env) {
-            cpu_exit(cpu_single_env);
-            cpu_single_env->stop = 1;
-        }
+        cpu_stop_current();
         return;
     }
     do_vm_stop(reason);
diff --git a/cpus.h b/cpus.h
index bf4d9bb..4cadb64 100644
--- a/cpus.h
+++ b/cpus.h
@@ -6,6 +6,7 @@ int qemu_init_main_loop(void);
 void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
+void cpu_stop_current(void);
 
 /* vl.c */
 extern int smp_cores;
diff --git a/vl.c b/vl.c
index ed2cdfa..5e3f7f2 100644
--- a/vl.c
+++ b/vl.c
@@ -1296,6 +1296,7 @@ void qemu_system_reset_request(void)
     } else {
         reset_requested = 1;
     }
+    cpu_stop_current();
     qemu_notify_event();
 }
 
commit aa2c364b4cf2fae4d9c8acf53ee4436ed533902d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Feb 1 22:15:42 2011 +0100

    Prevent abortion on multiple VCPU kicks
    
    If we call qemu_cpu_kick more than once before the target was able to
    process the signal, pthread_kill will fail, and qemu will abort. Prevent
    this by avoiding the redundant signal.
    
    This logic can be found in qemu-kvm as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-defs.h b/cpu-defs.h
index 8d4bf86..db809ed 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -205,6 +205,7 @@ typedef struct CPUWatchpoint {
     uint32_t stopped; /* Artificially stopped */                        \
     struct QemuThread *thread;                                          \
     struct QemuCond *halt_cond;                                         \
+    int thread_kicked;                                                  \
     struct qemu_work_item *queued_work_first, *queued_work_last;        \
     const char *cpu_model_str;                                          \
     struct KVMState *kvm_state;                                         \
diff --git a/cpus.c b/cpus.c
index 4c9928e..ab6e40e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -481,6 +481,7 @@ static void qemu_wait_io_event_common(CPUState *env)
         qemu_cond_signal(&qemu_pause_cond);
     }
     flush_queued_work(env);
+    env->thread_kicked = false;
 }
 
 static void qemu_tcg_wait_io_event(void)
@@ -648,7 +649,10 @@ void qemu_cpu_kick(void *_env)
 {
     CPUState *env = _env;
     qemu_cond_broadcast(env->halt_cond);
-    qemu_thread_signal(env->thread, SIG_IPI);
+    if (!env->thread_kicked) {
+        qemu_thread_signal(env->thread, SIG_IPI);
+        env->thread_kicked = true;
+    }
 }
 
 int qemu_cpu_self(void *_env)
commit 16fde5f2c2788232b16c06d34d0459a5c1ec1f6c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 17:36:19 2011 +0100

    qcow2: Fix order in L2 table COW
    
    When copying L2 tables (this happens only with internal snapshots), the order
    wasn't completely safe, so that after a crash you could end up with a L2 table
    that has too low refcount, possibly leading to corruption in the long run.
    
    This patch puts the operations in the right order: First allocate the new
    L2 table and replace the reference, and only then decrease the refcount of the
    old table.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 437aaa8..750abe3 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -515,13 +515,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
             return ret;
         }
     } else {
-        /* FIXME Order */
-        if (l2_offset)
-            qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
+        /* First allocate a new L2 table (and do COW if needed) */
         ret = l2_allocate(bs, l1_index, &l2_table);
         if (ret < 0) {
             return ret;
         }
+
+        /* Then decrease the refcount of the old table */
+        if (l2_offset) {
+            qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
+        }
         l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
     }
 
commit a9ae2bffea62ce5158be7475fe41e5fba6d026c1
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Feb 8 15:12:39 2011 +0100

    blockdev: Plug memory leak in drive_init() error paths
    
    Should have spotted this when doing commit 319ae529.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 24d7658..0690cc8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -526,7 +526,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     } else if (ro == 1) {
         if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
             error_report("readonly not supported by this bus type");
-            return NULL;
+            goto err;
         }
     }
 
@@ -536,12 +536,19 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     if (ret < 0) {
         error_report("could not open disk image %s: %s",
                      file, strerror(-ret));
-        return NULL;
+        goto err;
     }
 
     if (bdrv_key_required(dinfo->bdrv))
         autostart = 0;
     return dinfo;
+
+err:
+    bdrv_delete(dinfo->bdrv);
+    qemu_free(dinfo->id);
+    QTAILQ_REMOVE(&drives, dinfo, next);
+    qemu_free(dinfo);
+    return NULL;
 }
 
 void do_commit(Monitor *mon, const QDict *qdict)
commit 2753d4a5fa44d980cc6a279f323a12ca8d172972
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Feb 8 15:12:38 2011 +0100

    blockdev: Plug memory leak in drive_uninit()
    
    Started leaking in commit 1dae12e6.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index ecfadc1..24d7658 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -182,6 +182,7 @@ static void drive_uninit(DriveInfo *dinfo)
 {
     qemu_opts_del(dinfo->opts);
     bdrv_delete(dinfo->bdrv);
+    qemu_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
     qemu_free(dinfo);
 }
commit b9eaf9ecb15a9c69a592f386159163d5efc3b919
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 11:25:53 2011 +0100

    qemu-img: Improve error messages for failed bdrv_open
    
    Output the error message string of the bdrv_open return code. Also set a
    non-empty device name for the images because the unknown feature error message
    includes it.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-img.c b/qemu-img.c
index 4a37358..7e3cc4c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -213,8 +213,9 @@ static BlockDriverState *bdrv_new_open(const char *filename,
     BlockDriverState *bs;
     BlockDriver *drv;
     char password[256];
+    int ret;
 
-    bs = bdrv_new("");
+    bs = bdrv_new("image");
 
     if (fmt) {
         drv = bdrv_find_format(fmt);
@@ -225,10 +226,13 @@ static BlockDriverState *bdrv_new_open(const char *filename,
     } else {
         drv = NULL;
     }
-    if (bdrv_open(bs, filename, flags, drv) < 0) {
-        error_report("Could not open '%s'", filename);
+
+    ret = bdrv_open(bs, filename, flags, drv);
+    if (ret < 0) {
+        error_report("Could not open '%s': %s", filename, strerror(-ret));
         goto fail;
     }
+
     if (bdrv_is_encrypted(bs)) {
         printf("Disk image '%s' is encrypted.\n", filename);
         if (read_password(password, sizeof(password)) < 0) {
commit 10b758e85c9b38b4b370cff81435f6ed26024a26
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 11:13:26 2011 +0100

    qed: Report error for unsupported features
    
    Instead of just returning -ENOTSUP, generate a more detailed error.
    
    Unfortunately we don't have a helpful text for features that we don't know yet,
    so just print the feature mask. It might be useful at least if someone asks for
    help.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qed.c b/block/qed.c
index 3273448..75ae244 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -14,6 +14,7 @@
 
 #include "trace.h"
 #include "qed.h"
+#include "qerror.h"
 
 static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
 {
@@ -311,7 +312,13 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
         return -EINVAL;
     }
     if (s->header.features & ~QED_FEATURE_MASK) {
-        return -ENOTSUP; /* image uses unsupported feature bits */
+        /* image uses unsupported feature bits */
+        char buf[64];
+        snprintf(buf, sizeof(buf), "%" PRIx64,
+            s->header.features & ~QED_FEATURE_MASK);
+        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+            bs->device_name, "QED", buf);
+        return -ENOTSUP;
     }
     if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
         return -EINVAL;
commit e8cdcec123facf0ed273d941caeeeb9b08f14955
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 11:11:07 2011 +0100

    qcow2: Report error for version > 2
    
    The qcow2 driver is now declared responsible for any QCOW image that has
    version 2 or greater (before this, version 3 would be detected as raw).
    
    For everything newer than version 2, an error is reported.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 551b3c2..75b8bec 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -28,6 +28,7 @@
 #include "aes.h"
 #include "block/qcow2.h"
 #include "qemu-error.h"
+#include "qerror.h"
 
 /*
   Differences with QCOW:
@@ -59,7 +60,7 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
 
     if (buf_size >= sizeof(QCowHeader) &&
         be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
-        be32_to_cpu(cow_header->version) == QCOW_VERSION)
+        be32_to_cpu(cow_header->version) >= QCOW_VERSION)
         return 100;
     else
         return 0;
@@ -163,10 +164,18 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     be64_to_cpus(&header.snapshots_offset);
     be32_to_cpus(&header.nb_snapshots);
 
-    if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) {
+    if (header.magic != QCOW_MAGIC) {
         ret = -EINVAL;
         goto fail;
     }
+    if (header.version != QCOW_VERSION) {
+        char version[64];
+        snprintf(version, sizeof(version), "QCOW version %d", header.version);
+        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+            bs->device_name, "qcow2", version);
+        ret = -ENOTSUP;
+        goto fail;
+    }
     if (header.cluster_bits < MIN_CLUSTER_BITS ||
         header.cluster_bits > MAX_CLUSTER_BITS) {
         ret = -EINVAL;
commit f54e3641122e51c6343d587805422642f307462e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 11:09:38 2011 +0100

    qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qerror.c b/qerror.c
index 9d0cdeb..4855604 100644
--- a/qerror.c
+++ b/qerror.c
@@ -201,6 +201,11 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "An undefined error has ocurred",
     },
     {
+        .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+        .desc      = "'%(device)' uses a %(format) feature which is not "
+                     "supported by this qemu version: %(feature)",
+    },
+    {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
diff --git a/qerror.h b/qerror.h
index b0f69da..f732d45 100644
--- a/qerror.h
+++ b/qerror.h
@@ -165,6 +165,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_UNDEFINED_ERROR \
     "{ 'class': 'UndefinedError', 'data': {} }"
 
+#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
+    "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"
+
 #define QERR_VNC_SERVER_FAILED \
     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
 
commit 8af364884355b3f0c5d60a2d2f427927739658ea
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Feb 9 10:26:06 2011 +0100

    qcow2: Fix error handling for reading compressed clusters
    
    When reading a compressed cluster failed, qcow2 falsely returned success.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 5fb8c66..437aaa8 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -878,11 +878,11 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
         BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
         ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors);
         if (ret < 0) {
-            return -1;
+            return ret;
         }
         if (decompress_buffer(s->cluster_cache, s->cluster_size,
                               s->cluster_data + sector_offset, csize) < 0) {
-            return -1;
+            return -EIO;
         }
         s->cluster_cache_offset = coffset;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index 647c2a4..551b3c2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -497,8 +497,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (qcow2_decompress_cluster(bs, acb->cluster_offset) < 0)
+        ret = qcow2_decompress_cluster(bs, acb->cluster_offset);
+        if (ret < 0) {
             goto done;
+        }
 
         qemu_iovec_from_buffer(&acb->hd_qiov,
             s->cluster_cache + index_in_cluster * 512,
commit 3ab4c7e92d39d40e6dc0bdb1c2320889543691cb
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Feb 8 18:12:35 2011 +0100

    qcow2: Fix error handling for immediate backing file read failure
    
    Requests could return success even though they failed when bdrv_aio_readv
    returned NULL for a backing file read.
    
    Reported-by: Chunqiang Tang <ctang at us.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 28338bf..647c2a4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -479,8 +479,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
                                     &acb->hd_qiov, n1, qcow2_aio_read_cb, acb);
-                if (acb->hd_aiocb == NULL)
+                if (acb->hd_aiocb == NULL) {
+                    ret = -EIO;
                     goto done;
+                }
             } else {
                 ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb);
                 if (ret < 0)
commit e0d9c6f93729c9bfc98fcafcd73098bb8e131aeb
Author: Chunqiang Tang <ctang at us.ibm.com>
Date:   Thu Feb 3 10:12:49 2011 -0500

    QCOW2: bug fix - read base image beyond its size
    
    This patch fixes the following bug in QCOW2. For a QCOW2 image that is larger
    than its base image, when handling a read request straddling over the end of the
    base image, the QCOW2 driver attempts to read beyond the end of the base image
    and the request would fail.
    
    This bug was found by Fast Virtual Disk (FVD)'s fully automated testing tool.
    The following test triggered the bug.
    
    dd if=/dev/zero of=/var/ramdisk/truth.raw count=0 bs=1 seek=1098561536
    dd if=/dev/zero of=/var/ramdisk/zero-500M.raw count=0 bs=1 seek=593099264
    ./qemu-img create -f qcow2 -ocluster_size=65536,backing_fmt=blksim -b /var/ramdisk/zero-500M.raw /var/ramdisk/test.qcow2 1098561536
    ./qemu-io --auto --seed=30477694 --truth=/var/ramdisk/truth.raw --format=qcow2 --test=blksim:/var/ramdisk/test.qcow2 --verify_write=true --compare_before=false --compare_after=true --round=100000 --parallel=100 --io_size=10485760 --fail_prob=0 --cancel_prob=0 --instant_qemubh=true
    
    Signed-off-by: Chunqiang Tang <ctang at us.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index a1773e4..28338bf 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -355,7 +355,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
     else
         n1 = bs->total_sectors - sector_num;
 
-    qemu_iovec_memset(qiov, 0, 512 * (nb_sectors - n1));
+    qemu_iovec_memset_skip(qiov, 0, 512 * (nb_sectors - n1), 512 * n1);
 
     return n1;
 }
@@ -478,8 +478,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
             if (n1 > 0) {
                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
-                                    &acb->hd_qiov, acb->cur_nr_sectors,
-				    qcow2_aio_read_cb, acb);
+                                    &acb->hd_qiov, n1, qcow2_aio_read_cb, acb);
                 if (acb->hd_aiocb == NULL)
                     goto done;
             } else {
diff --git a/cutils.c b/cutils.c
index 8d562b2..f9a7e36 100644
--- a/cutils.c
+++ b/cutils.c
@@ -267,6 +267,37 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count)
     }
 }
 
+void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
+                            size_t skip)
+{
+    int i;
+    size_t done;
+    void *iov_base;
+    uint64_t iov_len;
+
+    done = 0;
+    for (i = 0; (i < qiov->niov) && (done != count); i++) {
+        if (skip >= qiov->iov[i].iov_len) {
+            /* Skip the whole iov */
+            skip -= qiov->iov[i].iov_len;
+            continue;
+        } else {
+            /* Skip only part (or nothing) of the iov */
+            iov_base = (uint8_t*) qiov->iov[i].iov_base + skip;
+            iov_len = qiov->iov[i].iov_len - skip;
+            skip = 0;
+        }
+
+        if (done + iov_len > count) {
+            memset(iov_base, c, count - done);
+            break;
+        } else {
+            memset(iov_base, c, iov_len);
+        }
+        done += iov_len;
+    }
+}
+
 #ifndef _WIN32
 /* Sets a specific flag */
 int fcntl_setfl(int fd, int flag)
diff --git a/qemu-common.h b/qemu-common.h
index c7ff280..cb4b7e0 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -322,6 +322,8 @@ void qemu_iovec_reset(QEMUIOVector *qiov);
 void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf);
 void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
 void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
+void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
+                            size_t skip);
 
 struct Monitor;
 typedef struct Monitor Monitor;
commit 982aa95532a3a7b549695d5b3e18442975eecfb5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Fri Feb 4 09:22:14 2011 +0100

    Change snapshot_blkdev hmp to use correct argument type for device
    
    Pointed out by Markus
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 38e1eb7..372bef4 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -822,7 +822,7 @@ ETEXI
 
     {
         .name       = "snapshot_blkdev",
-        .args_type  = "device:s,snapshot_file:s?,format:s?",
+        .args_type  = "device:B,snapshot_file:s?,format:s?",
         .params     = "device [new-image-file] [format]",
         .help       = "initiates a live snapshot\n\t\t\t"
                       "of device. If a new image file is specified, the\n\t\t\t"


More information about the Spice-commits mailing list